@hzab/vite-config 0.0.2-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +83 -0
- package/LICENSE +21 -0
- package/README.md +173 -0
- package/dist/create-app-vite-config.cjs +426 -0
- package/dist/create-app-vite-config.cjs.map +1 -0
- package/dist/create-app-vite-config.d.cts +19 -0
- package/dist/create-app-vite-config.d.ts +19 -0
- package/dist/create-app-vite-config.js +415 -0
- package/dist/create-app-vite-config.js.map +1 -0
- package/dist/create-library-vite-config.cjs +281 -0
- package/dist/create-library-vite-config.cjs.map +1 -0
- package/dist/create-library-vite-config.d.cts +31 -0
- package/dist/create-library-vite-config.d.ts +31 -0
- package/dist/create-library-vite-config.js +268 -0
- package/dist/create-library-vite-config.js.map +1 -0
- package/dist/create-package-vitest-config.cjs +73 -0
- package/dist/create-package-vitest-config.cjs.map +1 -0
- package/dist/create-package-vitest-config.d.cts +12 -0
- package/dist/create-package-vitest-config.d.ts +12 -0
- package/dist/create-package-vitest-config.js +67 -0
- package/dist/create-package-vitest-config.js.map +1 -0
- package/dist/create-vite-config.cjs +438 -0
- package/dist/create-vite-config.cjs.map +1 -0
- package/dist/create-vite-config.d.cts +17 -0
- package/dist/create-vite-config.d.ts +17 -0
- package/dist/create-vite-config.js +427 -0
- package/dist/create-vite-config.js.map +1 -0
- package/dist/index.cjs +631 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +603 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/copy.cjs +16 -0
- package/dist/plugins/copy.cjs.map +1 -0
- package/dist/plugins/copy.d.cts +18 -0
- package/dist/plugins/copy.d.ts +18 -0
- package/dist/plugins/copy.js +13 -0
- package/dist/plugins/copy.js.map +1 -0
- package/dist/plugins/hash-deploy.cjs +128 -0
- package/dist/plugins/hash-deploy.cjs.map +1 -0
- package/dist/plugins/hash-deploy.d.cts +56 -0
- package/dist/plugins/hash-deploy.d.ts +56 -0
- package/dist/plugins/hash-deploy.js +119 -0
- package/dist/plugins/hash-deploy.js.map +1 -0
- package/dist/plugins/less-tilde.cjs +32 -0
- package/dist/plugins/less-tilde.cjs.map +1 -0
- package/dist/plugins/less-tilde.d.cts +36 -0
- package/dist/plugins/less-tilde.d.ts +36 -0
- package/dist/plugins/less-tilde.js +29 -0
- package/dist/plugins/less-tilde.js.map +1 -0
- package/dist/plugins/lifecycle.cjs +28 -0
- package/dist/plugins/lifecycle.cjs.map +1 -0
- package/dist/plugins/lifecycle.d.cts +20 -0
- package/dist/plugins/lifecycle.d.ts +20 -0
- package/dist/plugins/lifecycle.js +26 -0
- package/dist/plugins/lifecycle.js.map +1 -0
- package/dist/plugins/public-assets.cjs +28 -0
- package/dist/plugins/public-assets.cjs.map +1 -0
- package/dist/plugins/public-assets.d.cts +17 -0
- package/dist/plugins/public-assets.d.ts +17 -0
- package/dist/plugins/public-assets.js +26 -0
- package/dist/plugins/public-assets.js.map +1 -0
- package/dist/plugins/public-config.cjs +31 -0
- package/dist/plugins/public-config.cjs.map +1 -0
- package/dist/plugins/public-config.d.cts +20 -0
- package/dist/plugins/public-config.d.ts +20 -0
- package/dist/plugins/public-config.js +29 -0
- package/dist/plugins/public-config.js.map +1 -0
- package/dist/plugins/react-compiler.cjs +22 -0
- package/dist/plugins/react-compiler.cjs.map +1 -0
- package/dist/plugins/react-compiler.d.cts +24 -0
- package/dist/plugins/react-compiler.d.ts +24 -0
- package/dist/plugins/react-compiler.js +16 -0
- package/dist/plugins/react-compiler.js.map +1 -0
- package/dist/plugins/relative-base.cjs +19 -0
- package/dist/plugins/relative-base.cjs.map +1 -0
- package/dist/plugins/relative-base.d.cts +9 -0
- package/dist/plugins/relative-base.d.ts +9 -0
- package/dist/plugins/relative-base.js +17 -0
- package/dist/plugins/relative-base.js.map +1 -0
- package/dist/plugins/stub-less.cjs +26 -0
- package/dist/plugins/stub-less.cjs.map +1 -0
- package/dist/plugins/stub-less.d.cts +9 -0
- package/dist/plugins/stub-less.d.ts +9 -0
- package/dist/plugins/stub-less.js +24 -0
- package/dist/plugins/stub-less.js.map +1 -0
- package/dist/plugins/svg-react.cjs +70 -0
- package/dist/plugins/svg-react.cjs.map +1 -0
- package/dist/plugins/svg-react.d.cts +28 -0
- package/dist/plugins/svg-react.d.ts +28 -0
- package/dist/plugins/svg-react.js +63 -0
- package/dist/plugins/svg-react.js.map +1 -0
- package/dist/svg-react-runtime.cjs +4 -0
- package/dist/svg-react-runtime.cjs.map +1 -0
- package/dist/svg-react-runtime.d.cts +2 -0
- package/dist/svg-react-runtime.d.ts +2 -0
- package/dist/svg-react-runtime.js +3 -0
- package/dist/svg-react-runtime.js.map +1 -0
- package/dist/types.cjs +4 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +291 -0
- package/dist/types.d.ts +291 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/vitest-types.cjs +4 -0
- package/dist/vitest-types.cjs.map +1 -0
- package/dist/vitest-types.d.cts +22 -0
- package/dist/vitest-types.d.ts +22 -0
- package/dist/vitest-types.js +3 -0
- package/dist/vitest-types.js.map +1 -0
- package/dist/vitest.cjs +73 -0
- package/dist/vitest.cjs.map +1 -0
- package/dist/vitest.d.cts +4 -0
- package/dist/vitest.d.ts +4 -0
- package/dist/vitest.js +67 -0
- package/dist/vitest.js.map +1 -0
- package/docs/README.md +15 -0
- package/docs/abt-management-ui/vite.config.mts +226 -0
- package/docs/api.md +366 -0
- package/docs/migration-from-webpack.md +722 -0
- package/docs/sync-public-path.md +52 -0
- package/docs/vite-config-integration.md +476 -0
- package/docs/vite-pnpm-integration.md +279 -0
- package/docs/vs-ccc-vite-config.md +26 -0
- package/docs/webpack-gap.md +107 -0
- package/package.json +113 -0
- package/src/client.d.ts +9 -0
- package/src/create-app-vite-config.ts +218 -0
- package/src/create-library-vite-config.ts +199 -0
- package/src/create-package-vitest-config.ts +54 -0
- package/src/create-vite-config.ts +22 -0
- package/src/index.ts +42 -0
- package/src/plugins/copy.ts +25 -0
- package/src/plugins/hash-deploy.ts +199 -0
- package/src/plugins/less-tilde.ts +44 -0
- package/src/plugins/lifecycle.ts +40 -0
- package/src/plugins/public-assets.ts +28 -0
- package/src/plugins/public-config.ts +34 -0
- package/src/plugins/react-compiler.ts +32 -0
- package/src/plugins/relative-base.ts +20 -0
- package/src/plugins/stub-less.ts +26 -0
- package/src/plugins/svg-react.ts +90 -0
- package/src/svg-react-runtime.ts +4 -0
- package/src/svg-react.d.ts +6 -0
- package/src/types.ts +314 -0
- package/src/vitest-types.ts +20 -0
- package/src/vitest.ts +2 -0
- package/templates/src/vite-env.d.ts +2 -0
- package/templates/tsconfig.json +12 -0
- package/templates/vite.config.ts +26 -0
|
@@ -0,0 +1,722 @@
|
|
|
1
|
+
# 从 `@hzab/webpack-config` 迁移到 `@hzab/vite-config`(页面应用 · 组件库)
|
|
2
|
+
|
|
3
|
+
面向当前使用 `@hzab/webpack-config` 的**页面应用**与**组件库**,切换到 `@hzab/vite-config`:
|
|
4
|
+
|
|
5
|
+
- 页面应用:`createPageConfig`(`webpack.config.js` + env)→ `createAppViteConfig`(`vite.config.ts`),见 §1–§9。
|
|
6
|
+
- 组件库:`createLibConfig`(UMD 产物)→ `createLibraryViteConfig`(`vite.config.ts`),见文末「组件库」节。
|
|
7
|
+
|
|
8
|
+
能力差距与设计定位见 [相对 webpack-config](./webpack-gap.md);工厂完整选项见 [API](./api.md)。
|
|
9
|
+
真实迁移案例(`abt-management-ui` 从 0 到 1 的完整落地)与通用排障方法见
|
|
10
|
+
[接入记录](./vite-config-integration.md) / [Vite + pnpm 排障手册](./vite-pnpm-integration.md)。
|
|
11
|
+
|
|
12
|
+
### 已迁移项目配置文件
|
|
13
|
+
|
|
14
|
+
- [abt-management-ui](./abt-management-ui/vite.config.mts)
|
|
15
|
+
|
|
16
|
+
## 1. 依赖变更
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# 新增(@hzab/vite-config 的 peer 依赖需消费方安装)
|
|
20
|
+
pnpm add -D @hzab/vite-config vite@^8 @vitejs/plugin-react@^6 @vitejs/plugin-basic-ssl@^2 @rolldown/plugin-babel@^0.2 vite-plugin-html@^3 vite-plugin-static-copy@^4 @originjs/vite-plugin-commonjs@1 cross-env@7 prettier@3
|
|
21
|
+
|
|
22
|
+
# 启用 svg 组件通道(svgr)时另装可选 peer
|
|
23
|
+
pnpm add -D @svgr/core @svgr/plugin-jsx @svgr/plugin-svgo
|
|
24
|
+
|
|
25
|
+
# 删除 webpack 工具链
|
|
26
|
+
pnpm remove webpack webpack-cli webpack-dev-server
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
- 删除根 `webpack.config.js`,及不再被使用的 babel 插件依赖(webpack-config 2.0 起 babel
|
|
30
|
+
插件由消费方声明,切到 Vite 后按实际残留清理)。
|
|
31
|
+
- 开发工具自声明:`@hzab/webpack-config@1.3.1` 曾将 prettier / eslint / @typescript-eslint/*
|
|
32
|
+
/ husky / lint-staged / typescript / cross-env 误置于 dependencies 靠提升隐式提供;`pnpm remove`
|
|
33
|
+
后这些二进制一并消失,pre-commit(lint-staged 的 `prettier --write`)与 scripts(`tsc` /
|
|
34
|
+
`cross-env`)会报 `'prettier' 不是内部或外部命令`(Windows)或 `command not found`。请按
|
|
35
|
+
实际使用在 devDependencies 自声明,例如 `pnpm add -D prettier eslint husky lint-staged
|
|
36
|
+
typescript cross-env @typescript-eslint/parser @typescript-eslint/eslint-plugin`;完整清单
|
|
37
|
+
见 [webpack-config 迁移指南](../../webpack-config/docs/migration.md) 第 2 条。
|
|
38
|
+
- 开发端口默认 5173(webpack 默认 3000),用 `vite.server.port` 显式恢复。
|
|
39
|
+
|
|
40
|
+
## 2. 新增根 `vite.config.ts`
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import path from "node:path";
|
|
44
|
+
import { fileURLToPath } from "node:url";
|
|
45
|
+
import { defineConfig } from "vite";
|
|
46
|
+
import { createAppViteConfig } from "@hzab/vite-config";
|
|
47
|
+
|
|
48
|
+
const rootDir = path.dirname(fileURLToPath(import.meta.url));
|
|
49
|
+
|
|
50
|
+
export default defineConfig(({ command, mode }) =>
|
|
51
|
+
createAppViteConfig({
|
|
52
|
+
rootDir,
|
|
53
|
+
command,
|
|
54
|
+
mode,
|
|
55
|
+
// 应用位于 monorepo 子目录时,指定 Git 仓库根(Hash 目录名的 commit 默认从 rootDir 读)
|
|
56
|
+
// repositoryRoot: path.resolve(rootDir, '../../'),
|
|
57
|
+
alias: {
|
|
58
|
+
"@": path.resolve(rootDir, "./src"),
|
|
59
|
+
// '@packages': ..., '@assets': ..., '@service': ..., // 原 resolve.alias
|
|
60
|
+
},
|
|
61
|
+
// 原 devServer.proxy
|
|
62
|
+
devProxy: { "/api": "http://localhost:13000" },
|
|
63
|
+
// 原 lessLoaderOptions
|
|
64
|
+
less: {
|
|
65
|
+
// additionalData: `@import url(@/size.less);`,
|
|
66
|
+
// modifyVars: { '@primary-color': '#1890ff' },
|
|
67
|
+
// javascriptEnabled: true, // formily 内联 JS 才需要(Vite 侧默认 false,见第 8 节)
|
|
68
|
+
// resolveTilde: true, // 开启 `~` 解析(默认关闭,项目含 `~antd` 时开)
|
|
69
|
+
},
|
|
70
|
+
// 原 isHash + hashPublicPath
|
|
71
|
+
hashDeploy: mode !== "development",
|
|
72
|
+
hashCleanup: { keep: 3 }, // 可选;默认永久保留旧版本
|
|
73
|
+
// base: 'https://test.com/aaa/', // 若 hashPublicPath 是固定 CDN 前缀
|
|
74
|
+
// 原 public-config 多环境复制
|
|
75
|
+
publicConfig: { mode, dest: "public/config" }, // 对齐 webpack 产物路径;默认产物 config/
|
|
76
|
+
// 注入 HTML 模板的 EJS 数据;仅 PUBLIC_PATH 由工厂始终注入,其余键(如 APP_TITLE)必须在此声明
|
|
77
|
+
htmlData: { APP_TITLE: "My App" },
|
|
78
|
+
svgr: true, // 启用 svg 组件通道,import 需从 ?svgEle 改为 ?react
|
|
79
|
+
// 原 devServer.https:basic-ssl 已在 peer 依赖里,置 true 即启 dev HTTPS
|
|
80
|
+
// useHttps: true,
|
|
81
|
+
// 原 CopyPlugin public → public/(默认开);public 目录在别处或不需要时改这里
|
|
82
|
+
// publicAssets: { dir: 'public' }, // false 关闭
|
|
83
|
+
// 原其它 CopyPlugin patterns(publicConfig 只负责 config 复制,不含这些)
|
|
84
|
+
// copy: { targets: [{ src: 'node_modules/some-sdk/assets/**/*', dest: 'sdk' }] },
|
|
85
|
+
vite: {
|
|
86
|
+
server: { port: 3000 }, // 原 devServer.port
|
|
87
|
+
// define: { ... }, // 原 processEnv / DefinePlugin
|
|
88
|
+
},
|
|
89
|
+
}),
|
|
90
|
+
);
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
接入时按需映射的几项(webpack 侧由 CopyPlugin / `devServer.https` / `beforeBuild` 承担):
|
|
94
|
+
|
|
95
|
+
- **`repositoryRoot`**:Hash 目录名里的 commit 默认从 `rootDir` 读。应用在 monorepo 子目录时,
|
|
96
|
+
传 Git 仓库根,否则会取子目录(或取不到 commit);不传时工厂用 `process.cwd()` / `rootDir`。
|
|
97
|
+
- **`publicAssets`**:工厂默认开启,把根 `public/` 复制到产物 `public/`(`index.html` 的
|
|
98
|
+
`<%= PUBLIC_PATH %>public/icons.svg` 就依赖它,见 §3)。webpack 的 public 目录不在包根、
|
|
99
|
+
或本就不想要这份拷贝时,传 `publicAssets: false` 或 `{ dir }`。
|
|
100
|
+
- **`copy`**:webpack 里额外的 CopyPlugin 模式(如把 `node_modules/some-sdk/assets` 拷到 `sdk`)
|
|
101
|
+
对应 `copy` / `copyPlugin`;`publicConfig` 只复制 config,不管这些静态目录。
|
|
102
|
+
- **`useHttps`**:原 `devServer.https` 用 `useHttps: true`(`@vitejs/plugin-basic-ssl` 已在依赖里)。
|
|
103
|
+
- 构建生命周期:原 `beforeBuild` / `userConf` 对应 `vite`(`mergeConfig`)→ `configure` 回调;
|
|
104
|
+
有「构建成功后」逻辑(写额外产物、发通知)用 `onRun` / `onDone`(`onDone` 在 Hash 根入口写入后、
|
|
105
|
+
写入失败不触发)。
|
|
106
|
+
|
|
107
|
+
> **React Compiler**:工厂默认 `reactCompiler: "build-only"`(仅 build 启用),但
|
|
108
|
+
> `babel-plugin-react-compiler` 不在 peer 依赖里。未安装时 build 报
|
|
109
|
+
> `Cannot find package 'babel-plugin-react-compiler'`;不启用就显式 `reactCompiler: false`,
|
|
110
|
+
> 要用则 `pnpm add -D babel-plugin-react-compiler`。
|
|
111
|
+
|
|
112
|
+
`~antd/...` 这类 webpack 「~」前缀写法(含第三方包自带的 `~antd` 导入,如
|
|
113
|
+
`c-formily-antd` 的 `style.less`)**默认不解析**(`less.resolveTilde` 默认 `false`)。
|
|
114
|
+
被迁移项目含 `~antd`(尤其引用了带 `~` 的第三方 less)时,显式 `less: { resolveTilde: true }`
|
|
115
|
+
开启内置 `~` 解析(从 node_modules),无需改写为裸包名。注意:antd(v4)主题 less 含内联 JS
|
|
116
|
+
(`color(~`...`)`),仍需显式 `less: { javascriptEnabled: true }`(见第 8 节)。
|
|
117
|
+
|
|
118
|
+
## 3. 入口与类型声明
|
|
119
|
+
|
|
120
|
+
- 新增根 `index.html`(webpack 由 html-webpack-plugin 生成,Vite 需要手写入口):
|
|
121
|
+
|
|
122
|
+
```html
|
|
123
|
+
<!doctype html>
|
|
124
|
+
<html lang="zh-CN">
|
|
125
|
+
<head>
|
|
126
|
+
<meta charset="UTF-8" />
|
|
127
|
+
<title><%= APP_TITLE %></title>
|
|
128
|
+
<link rel="icon" href="<%= PUBLIC_PATH %>public/icons.svg" />
|
|
129
|
+
</head>
|
|
130
|
+
<body>
|
|
131
|
+
<div id="root"></div>
|
|
132
|
+
<script type="module" src="/src/index.tsx"></script>
|
|
133
|
+
</body>
|
|
134
|
+
</html>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
`<%= PUBLIC_PATH %>` 由工厂注入(`htmlData` 键与之合并,同名键以工厂为准);`APP_TITLE` 是
|
|
138
|
+
`htmlData` 示例键,必须在上方配置里声明,否则 EJS 会渲染成字面 "undefined"。多环境
|
|
139
|
+
config 的引用路径须与 `publicConfig.dest` 对齐:§2 用 `dest: "public/config"` 则此处应为
|
|
140
|
+
`<%= PUBLIC_PATH %>public/config/config.js`;用默认 `dest: "config"` 则为
|
|
141
|
+
`<%= PUBLIC_PATH %>config/config.js`。
|
|
142
|
+
`<link rel="icon" href="<%= PUBLIC_PATH %>public/icons.svg" />` 里的 `public/icons.svg`
|
|
143
|
+
来自 §2 复制的静态目录(`publicAssets`),不是 `publicConfig`。
|
|
144
|
+
|
|
145
|
+
- 新增 `src/vite-env.d.ts`:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
/// <reference types="vite/client" />
|
|
149
|
+
/// <reference types="@hzab/vite-config/client" />
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
- svg 组件类型(三选一,任选其一即可,不必叠加):
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
/// <reference types="@hzab/vite-config/svg-react" />
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
或在 tsconfig `compilerOptions.types` 数组加入 `"@hzab/vite-config/svg-react"`
|
|
159
|
+
(注意 `types` 数组会限制自动加载的 `@types/*` 包,需保留原有项如 `"node"`、`"vite/client"`);
|
|
160
|
+
或副作用导入(等价加载类型声明):
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
import "@hzab/vite-config/svg-react";
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## 4. 源码替换
|
|
167
|
+
|
|
168
|
+
| webpack 写法 | Vite 写法 |
|
|
169
|
+
| ---------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
170
|
+
| `import X from 'x.svg?svgEle'` | `import X from 'x.svg?react'`(并启用 svgr) |
|
|
171
|
+
| `process.env.WEBPACK_ENV` | `import.meta.env.MODE` |
|
|
172
|
+
| `process.env.WEBPACK_PUBLIC_PATH` | 打包资源用 `import.meta.env.BASE_URL`;根入口 `fetch` 用 `import.meta.env.PUBLIC_PATH` |
|
|
173
|
+
| `process.env.WEBPACK_HASH` | 已含在 `import.meta.env.PUBLIC_PATH`;构建 / 部署侧仍可读 `buildDirHash` / `hash.txt` |
|
|
174
|
+
| `process.env.PACKAGE_VERSION` / 自定义键 | `vite.define`(从应用 package.json 读) |
|
|
175
|
+
|
|
176
|
+
- `process.env.PACKAGE_VERSION` / 自定义键:经 `vite.define` 从**应用** `package.json` 读取注入,
|
|
177
|
+
不要学 webpack 注入工厂包版本。`define` 在构建时做字面替换,源码中仍写
|
|
178
|
+
`process.env.PACKAGE_VERSION`:
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
import { readFileSync } from "node:fs";
|
|
182
|
+
import path from "node:path";
|
|
183
|
+
import { fileURLToPath } from "node:url";
|
|
184
|
+
import { defineConfig } from "vite";
|
|
185
|
+
import { createAppViteConfig } from "@hzab/vite-config";
|
|
186
|
+
|
|
187
|
+
const rootDir = path.dirname(fileURLToPath(import.meta.url));
|
|
188
|
+
|
|
189
|
+
// 从应用 package.json 读取版本号
|
|
190
|
+
const { version } = JSON.parse(readFileSync(path.resolve(rootDir, "package.json"), "utf-8"));
|
|
191
|
+
|
|
192
|
+
export default defineConfig(({ command, mode }) =>
|
|
193
|
+
createAppViteConfig({
|
|
194
|
+
rootDir,
|
|
195
|
+
command,
|
|
196
|
+
mode,
|
|
197
|
+
vite: {
|
|
198
|
+
define: {
|
|
199
|
+
"process.env.PACKAGE_VERSION": JSON.stringify(version),
|
|
200
|
+
// 自定义键示例:透传构建时环境变量(未设置时回退默认值)
|
|
201
|
+
// 'process.env.CUSTOM_KEY': JSON.stringify(process.env.CUSTOM_KEY ?? ''),
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
}),
|
|
205
|
+
);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
> 页面应用统一用 `createAppViteConfig`:工厂默认入口 `createViteConfig` 虽是它的快捷版本,
|
|
209
|
+
> 但默认值不同(`reactCompiler: false`、`openBrowser: false`、`rootDir = process.cwd()`),
|
|
210
|
+
> 用它会把 §2 里 `reactCompiler: "build-only"` 与自动开浏览器**悄悄关掉**,页面应用不要用。
|
|
211
|
+
|
|
212
|
+
- `process.env.*` 在浏览器端:webpack 会 polyfill 全局 `process`(并注入 `process.env.*`);
|
|
213
|
+
Vite **只静态替换 `process.env.NODE_ENV`**,其余键在应用源码与预打包依赖里**原样残留**
|
|
214
|
+
→ 浏览器报 `ReferenceError: process is not defined`(多出现在自有 axios 封装或 `@hzab/*`
|
|
215
|
+
源码包)。修复**两步缺一不可**:
|
|
216
|
+
|
|
217
|
+
1. `vite.define` 注入全部自定义 `process.env.*`(见上方示例),覆盖应用源码与 build(产物无裸 `process.env.*`);
|
|
218
|
+
2. `index.html` 顶部加全局 `process` 兜底——**`optimizeDeps` 预打包不经过 `define`**,被预构
|
|
219
|
+
建的源码包(如 `@hzab/data-model`)内部的 `process.env.*` 在 dev 仍以裸 `process` 残留:
|
|
220
|
+
|
|
221
|
+
```html
|
|
222
|
+
<script>
|
|
223
|
+
window.process = window.process || { env: {} };
|
|
224
|
+
</script>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
- `?svgEle` → `?react`:全仓替换 import,两契约不兼容;未启用 `svgr` 时普通 `*.svg`
|
|
228
|
+
仍是资源 URL。
|
|
229
|
+
- `ProvidePlugin({ React })` 不需要:`@vitejs/plugin-react` 默认 automatic JSX runtime。
|
|
230
|
+
|
|
231
|
+
## 5. package.json scripts
|
|
232
|
+
|
|
233
|
+
基础脚本如下:
|
|
234
|
+
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"dev": "vite",
|
|
238
|
+
"build": "vite build",
|
|
239
|
+
"preview": "vite preview"
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
多环境用 `--mode` 传参(缺省:`vite` 为 `development`、`vite build` 为 `production`):
|
|
244
|
+
|
|
245
|
+
```json
|
|
246
|
+
{
|
|
247
|
+
"dev": "vite",
|
|
248
|
+
"build": "vite build",
|
|
249
|
+
"build:test": "vite build --mode test",
|
|
250
|
+
"build:staging": "vite build --mode staging",
|
|
251
|
+
"preview": "vite preview"
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
多环境配置文件夹
|
|
256
|
+
|
|
257
|
+
```json
|
|
258
|
+
"dev": "cross-env PUBLIC_CONF_DIR=local vite --mode development",
|
|
259
|
+
"build-flow_dev": "cross-env PUBLIC_CONF_DIR=development vite build --mode production",
|
|
260
|
+
"build": "cross-env vite build --mode production",
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
`mode` 同时驱动三件事,多环境方案的本质是**对这三者做取舍**:
|
|
264
|
+
|
|
265
|
+
| `mode` 驱动 | 规则 |
|
|
266
|
+
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
267
|
+
| `publicConfig` 源目录 | 默认 `config/public-config/${mode}/*`;不想按 mode 命名目录就显式 `publicConfig: { mode, sourceGlob }` 指过去 |
|
|
268
|
+
| `hashDeploy` 是否生效 | 工厂内 `isHash = isBuild && hashDeploy && mode !== 'development'`,即**只有非 `development` 的 mode 才出 hash** |
|
|
269
|
+
| `import.meta.env.MODE` / `NODE_ENV` | 构建语义,第三方库常据此选分支,`production` 最稳 |
|
|
270
|
+
|
|
271
|
+
> **别用 `import.meta.env.PROD` / `DEV` 区分环境**:Vite 里**所有 `build` 都是 `PROD === true`**
|
|
272
|
+
> (`DEV` 同理只对 serve 为 `true`)。用 `PROD` 判断「是否生产」会让 `test` / 预发等 `--mode`
|
|
273
|
+
> 构建也拿到 `true`。要区分测试包与生产包,看 `import.meta.env.MODE`(本仓测试包是 `test`)。
|
|
274
|
+
|
|
275
|
+
`mode` 命名注意:本仓测试包是 `test`、本地 serve 是 `development`(webpack 可能叫 `local`),
|
|
276
|
+
目录名要与实际 `--mode` 对齐,或显式 `sourceGlob`。
|
|
277
|
+
|
|
278
|
+
> **`isHash` 是理解多环境配置的钥匙**:构建目录名只把 `development` 当作"不出 hash"的唯一特例,
|
|
279
|
+
> 而非"只有生产才 hash"。因此 webpack 时代常见的 `test` / 预发 / 多租户构建,**不能改用
|
|
280
|
+
> `--mode development`**——那会强制关掉 hash、`dist` 不再按版本落目录。要做到"该环境照常出 hash +
|
|
281
|
+
> 用该环境的 public-config",应把「选配置目录」和「Vite mode」**解耦**,见下方两种策略。
|
|
282
|
+
|
|
283
|
+
### 策略 A:每个环境一个 `mode`(环境目录名与 mode 一一对应)
|
|
284
|
+
|
|
285
|
+
环境少、`config/public-config/<env>/*` 目录名恰好能当 `--mode` 用时最省事:
|
|
286
|
+
|
|
287
|
+
```json
|
|
288
|
+
{
|
|
289
|
+
"dev": "vite --mode development",
|
|
290
|
+
"build": "vite build --mode production",
|
|
291
|
+
"build:test": "vite build --mode test", // hash 生效(非 development)
|
|
292
|
+
"build:staging": "vite build --mode staging" // hash 生效(非 development)
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
- `publicConfig: { mode }` 无需额外配置,源目录自动取 `config/public-config/${mode}/*`。
|
|
297
|
+
- 局限:`mode` 同时是构建语义(`NODE_ENV` / `import.meta.env.MODE`)。若依赖判断
|
|
298
|
+
`NODE_ENV === 'production'` 才走对逻辑,用 `test` / `staging` 会让它拿不到 `production`;
|
|
299
|
+
且测试/预发与生产的差异若只差一个配置目录,也没必要拆成不同 mode。
|
|
300
|
+
|
|
301
|
+
### 策略 B:环境变量选目录 + 统一 `--mode production`(对齐 webpack `closeMulEnvConf`)
|
|
302
|
+
|
|
303
|
+
webpack 时代目录选择走 `closeMulEnvConf` 的 env 变量、hash 走 `isHash`,两者本就解耦。Vite 把两者
|
|
304
|
+
叠在 `mode` 上;要还原独立性,就把**目录选择**交给环境变量(变量名自定,示例用 `PUBLIC_CONF_DIR`),
|
|
305
|
+
`mode` 只保留构建语义:
|
|
306
|
+
|
|
307
|
+
```ts
|
|
308
|
+
// vite.config.ts
|
|
309
|
+
createAppViteConfig({
|
|
310
|
+
rootDir,
|
|
311
|
+
command,
|
|
312
|
+
mode,
|
|
313
|
+
hashDeploy: true, // mode 恒 production,恒生效;也可写 mode !== 'development'
|
|
314
|
+
publicConfig: {
|
|
315
|
+
mode: process.env.PUBLIC_CONF_DIR || mode, // 环境变量优先选目录;未设置回退 Vite mode
|
|
316
|
+
dest: "public/config",
|
|
317
|
+
},
|
|
318
|
+
});
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
```json
|
|
322
|
+
{
|
|
323
|
+
"dev": "cross-env PUBLIC_CONF_DIR=local vite --mode development", // dev 不 hash,符合预期
|
|
324
|
+
"build": "vite build --mode production",
|
|
325
|
+
"build:test": "cross-env PUBLIC_CONF_DIR=test vite build --mode production",
|
|
326
|
+
"build:tenant": "cross-env PUBLIC_CONF_DIR=tenant vite build --mode production",
|
|
327
|
+
"build:dbt": "cross-env PUBLIC_CONF_DIR=dbt vite build --mode production"
|
|
328
|
+
}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
- **所有 `*build*` 统一 `--mode production`**:保证 `isHash` 恒真、`NODE_ENV=production`,环境差异
|
|
332
|
+
完全由 `PUBLIC_CONF_DIR` 承载(选 `config/public-config/<env>/*`)。
|
|
333
|
+
- 目录名不再受 `development` / `production` 约束,可沿用 webpack 时代的 `local` / `dev_tenant` / `dbt` 等。
|
|
334
|
+
- Windows 下设置 env 变量需 `cross-env`:`pnpm add -D cross-env`。
|
|
335
|
+
|
|
336
|
+
## 6.(可选)Vitest 测试配置
|
|
337
|
+
|
|
338
|
+
页面应用如需接入 Vitest,用 `createPackageVitestConfig`(从 `@hzab/vite-config/vitest` 导入)。
|
|
339
|
+
测试文件 import less 时二选一:
|
|
340
|
+
|
|
341
|
+
- `stubLess: true`:普通 less 桩为空模块,`.module.less` 默认导出 identity stub,不编译 less;
|
|
342
|
+
- `stubLess: false`(默认):真实编译 less,需在 `vite.css.preprocessorOptions.less` 补齐
|
|
343
|
+
webpack 时代由 less-loader 提供的选项(如 formily 内联 JS 的 `javascriptEnabled: true`):
|
|
344
|
+
|
|
345
|
+
```ts
|
|
346
|
+
import path from "node:path";
|
|
347
|
+
import { defineConfig } from "vitest/config";
|
|
348
|
+
import { createPackageVitestConfig } from "@hzab/vite-config/vitest";
|
|
349
|
+
|
|
350
|
+
export default defineConfig(
|
|
351
|
+
createPackageVitestConfig({
|
|
352
|
+
packageRoot: __dirname,
|
|
353
|
+
react: true,
|
|
354
|
+
include: ["test/**/*.{test.ts,test.tsx}"],
|
|
355
|
+
// stubLess: true, // 简单桩掉 less;需要真实编译时用下方 vite 配置
|
|
356
|
+
vite: {
|
|
357
|
+
css: {
|
|
358
|
+
preprocessorOptions: {
|
|
359
|
+
less: {
|
|
360
|
+
javascriptEnabled: true, // 默认 false,formily 内联 JS 需显式开
|
|
361
|
+
// additionalData: `@import url(@/size.less);`, // 原 lessLoaderOptions.additionalData
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
}),
|
|
367
|
+
);
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
`less.javascriptEnabled` 默认是 **false**:Vite 的 less 处理只透传
|
|
371
|
+
`css.preprocessorOptions.less`(不注入该选项),Less 4 默认 `false`。旧项目里的「默认 true」
|
|
372
|
+
是 webpack-config 样式规则**强制**打开的,切到 Vite 后必须显式传。
|
|
373
|
+
|
|
374
|
+
## 7. 多环境 public-config 目录
|
|
375
|
+
|
|
376
|
+
- Vite 默认从 `config/public-config/${mode}/*` 复制到产物 `config/`;旧目录在别处时用
|
|
377
|
+
`publicConfig: { mode, sourceGlob }` 指过去。
|
|
378
|
+
- 产物路径默认 `config/`(运行时 `window.globalConfig` 从 `<%= PUBLIC_PATH %>config/config.js`
|
|
379
|
+
加载);要跟 webpack 一样落在 `public/config/` 则传 `dest: "public/config"`。
|
|
380
|
+
- `mode` 命名注意:`vite` 本地 dev 是 `development`(webpack 可能叫 `local`);目录名要与
|
|
381
|
+
实际 `--mode` 对齐,或显式 `sourceGlob`。
|
|
382
|
+
- 目录选择不想绑定 Vite `mode` 时,用环境变量优先:`publicConfig: { mode: process.env.PUBLIC_CONF_DIR || mode }`,
|
|
383
|
+
并让所有 build 脚本统一 `--mode production` 以恒出 hash(见 §5 策略 B)。
|
|
384
|
+
|
|
385
|
+
## 8. 已知缺口(webpack-gap.md 已记录,切换前知悉)
|
|
386
|
+
|
|
387
|
+
| 缺口 | 说明 |
|
|
388
|
+
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
389
|
+
| `timeHash: false` 无对等 | Vite hash 目录名恒为 `{commit}-{timestamp}`(`hashTimestamp: "datetime"` 可换格式) |
|
|
390
|
+
| `less.javascriptEnabled` 默认 false | Less 4 默认 `false`、Vite 不注入;webpack 样式规则强制 `true`,formily 内联 JS 需显式 `less: { javascriptEnabled: true }` |
|
|
391
|
+
| dev 无内置类型检查 | 原 ForkTsChecker;处理见下文「开发态类型检查」 |
|
|
392
|
+
| dev Mock 不内置 | 原 webpack-plugin-mock 独立端口;连真实后端用 `devProxy`,本地桩自挂 mock 插件 / MSW |
|
|
393
|
+
|
|
394
|
+
### 开发态类型检查
|
|
395
|
+
|
|
396
|
+
webpack dev 挂 `ForkTsCheckerWebpackPlugin({ async: true })`——启动/编译时**即时**报类型
|
|
397
|
+
错误。Vite 官方只转译(esbuild/oxc)、不查类型,vite-config 刻意不内置 checker。二选一:
|
|
398
|
+
|
|
399
|
+
**方案 A(零依赖,推荐)**:dev 靠 IDE 实时提示,类型错误由脚本/CI 拦截。
|
|
400
|
+
|
|
401
|
+
```json
|
|
402
|
+
{
|
|
403
|
+
"dev": "vite",
|
|
404
|
+
"typecheck": "tsc -b",
|
|
405
|
+
"build": "tsc -b && vite build"
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
tsconfig 需 `noEmit: true`(webpack 模板本就有;Vite 标准模板也是 `tsc -b` + noEmit)。
|
|
410
|
+
差别:类型错误不会在 dev 浏览器/终端即时浮现,仅 IDE 红线 + 提交/构建时拦截。
|
|
411
|
+
|
|
412
|
+
**方案 B(对齐 ForkTsChecker 即时体验)**:消费方自装社区插件(不是本包 peer),经工厂
|
|
413
|
+
`plugins` 选项接入:
|
|
414
|
+
|
|
415
|
+
```bash
|
|
416
|
+
pnpm add -D vite-plugin-checker # 0.14.5,peer vite >=5.4.21,兼容 Vite 8
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
```ts
|
|
420
|
+
import checker from "vite-plugin-checker";
|
|
421
|
+
|
|
422
|
+
createAppViteConfig({
|
|
423
|
+
rootDir,
|
|
424
|
+
command,
|
|
425
|
+
mode,
|
|
426
|
+
plugins: [checker({ typescript: true })], // dev 即时检查 + 浏览器 overlay
|
|
427
|
+
// checker({ typescript: true, buildMode: true }) 可让 build 也查
|
|
428
|
+
});
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
代价:tsc worker 常驻,启动/内存开销大于方案 A。重度依赖即时反馈的团队用方案 B 平滑过渡
|
|
432
|
+
(dev 用 checker、build 保留 `tsc -b`);否则方案 A 更轻。
|
|
433
|
+
|
|
434
|
+
**commit 时检查(提交前拦截)**:vite-config 只负责构建配置,不涉及 git 流程,没有
|
|
435
|
+
commit 时检查 TS 的操作(与 commit 的唯一关系是 hash 部署目录名取 commit hash)。提交前
|
|
436
|
+
检查由消费方仓库自配,与 webpack/vite 无关,方案 A 的 `typecheck` 脚本可直接复用:
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
# 方式一:husky + lint-staged(只查暂存文件,推荐)
|
|
440
|
+
pnpm add -D husky lint-staged
|
|
441
|
+
# package.json
|
|
442
|
+
{
|
|
443
|
+
"lint-staged": {
|
|
444
|
+
"*.{ts,tsx}": ["eslint --fix", "tsc --noEmit -p tsconfig.json"]
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
```bash
|
|
450
|
+
# 方式二:git hook 全量跑
|
|
451
|
+
# .husky/pre-commit
|
|
452
|
+
pnpm typecheck
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
Vite 原生覆盖(无需配置):TS/JSX 编译、CSS / CSS Modules / 构建抽 CSS、SPA
|
|
456
|
+
`historyApiFallback`、HMR、端口占用自增、生产 minify、文件系统缓存(`node_modules/.vite`)。
|
|
457
|
+
|
|
458
|
+
### CJS 依赖互操作(pnpm 严格隔离 + CJS 裸供)
|
|
459
|
+
|
|
460
|
+
统一根因:webpack 对 CJS 做 harmony 互操作兜底;Vite/Rolldown **只对预打包目标做 CJS→ESM
|
|
461
|
+
互操作**。pnpm 的严格隔离布局不提升 CJS-only 依赖,`optimizeDeps` 扫不到 → 源码被按原始 CJS
|
|
462
|
+
裸供浏览器。按现象与修复分为几类:
|
|
463
|
+
|
|
464
|
+
| 现象 | 根因 | 修复 |
|
|
465
|
+
| -------------------------------------------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
466
|
+
| `module is not defined` | 共享/传递 CJS-only 包未提升到顶层,optimizeDeps 发现不了(如 `react-is`) | 提升为直接依赖 + `optimizeDeps.include` |
|
|
467
|
+
| `require is not defined` | 父入口包被 commonjs 转换后,其 CJS 叶子包逐个独立裸供(es-shims 闭包) | 提升**入口包** + include,并同时**从 commonjs include 移除** |
|
|
468
|
+
| `does not provide an export named 'X'` | UMD bundle 具名导出静态分析识别不出(如 c-formily-antd / `@hzab/classnames-utils`) | alias 到带 `esm/` 或 `"type":"module"` 的原生 ESM 实例 |
|
|
469
|
+
| `Cannot set properties of undefined (setting 'X')` | UMD 顶层 `this` 被 Vite 当 ESM 供为 `undefined`(如 quickselect 传依赖) | alias 到 `"type":"module"` 的原生 ESM 实例 |
|
|
470
|
+
| CJS 包整体转换 | —— | `@originjs/vite-plugin-commonjs` / `vite-plugin-commonjs`(**只能产出 default,救不了具名导出**) |
|
|
471
|
+
|
|
472
|
+
> 取材方寸:查 `node_modules/.pnpm/<pkg>@*` 里是否有带 `esm/` 目录或 `"type":"module"` 的实例,
|
|
473
|
+
> 有就 alias 到它(优先原生 ESM),没有再走 commonjs 插件。**不要**用
|
|
474
|
+
> `import { createRequire } from 'node:module'` 这类 shim——浏览器端不存在 `node:module`。
|
|
475
|
+
|
|
476
|
+
以下是其中**最典型的一类——ESM default import 引用纯 CJS 依赖(default 导出缺失)**的详细修复。
|
|
477
|
+
|
|
478
|
+
Vite dev 报:
|
|
479
|
+
|
|
480
|
+
```text
|
|
481
|
+
Uncaught SyntaxError: The requested module '/node_modules/.pnpm/hoist-non-react-statics@3.3.2/.../dist/hoist-non-react-statics.cjs.js?v=XXXX' does not provide an export named 'default' (at observer.js?v=XXXX:13:8)
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
触发链:某个**未被预打包**的 ESM 源文件用 `import X from '<cjs 包>'` 默认导入一个纯 CJS 依赖。
|
|
485
|
+
实测为 `@formily/reactive-react@2.3.1` 的 `esm/observer.js`:
|
|
486
|
+
|
|
487
|
+
```js
|
|
488
|
+
import hoistNonReactStatics from "hoist-non-react-statics"; // ESM default import → CJS
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
该源文件没进 `optimizeDeps` 预打包,`hoist-non-react-statics`(`module.exports = fn`,无
|
|
492
|
+
`default`)也没被预打包,浏览器按原生 ESM 直接加载 `.cjs.js`,于是没有 `default` 导出。
|
|
493
|
+
webpack 的 harmony 互操作会自动兜底;Vite/Rolldown 只对预打包目标做 CJS→ESM 互操作,未进
|
|
494
|
+
预打包源码里的 deep CJS 依赖往往漏掉。
|
|
495
|
+
|
|
496
|
+
**修复步骤(按可靠性顺序):**
|
|
497
|
+
|
|
498
|
+
1. **彻底清缓存并完全重启**(改 `optimizeDeps` 后必做,Vite/Rolldown 不因配置变更自动重建):
|
|
499
|
+
|
|
500
|
+
```bash
|
|
501
|
+
# 停掉 dev server 后
|
|
502
|
+
rm -rf node_modules/.vite # Windows: rmdir /s /q node_modules\.vite
|
|
503
|
+
pnpm dev
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
2. **`include` 须连同引用方一起预打包**,只写 CJS 依赖本身往往无效——因为它可能已被其它
|
|
507
|
+
预打包 chunk 内联(`@hzab/list-render` 产物里就内联了 hoist),Rolldown 不再为它单独建 entry:
|
|
508
|
+
|
|
509
|
+
```ts
|
|
510
|
+
vite: {
|
|
511
|
+
optimizeDeps: {
|
|
512
|
+
include: [
|
|
513
|
+
'hoist-non-react-statics',
|
|
514
|
+
'@formily/reactive-react', // 真正 default import 它的包,须一起预打包
|
|
515
|
+
],
|
|
516
|
+
},
|
|
517
|
+
},
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
3. **兜底:Rolldown(Vite 8)下 `optimizeDeps.include` 可能不生效**——实测清缓存、改配置、
|
|
521
|
+
完全重启后,`.vite/deps/_metadata.json` 的 `optimized` 里仍**没有** `hoist-non-react-statics`
|
|
522
|
+
与 `@formily/reactive-react`(该 `optimized` 全是扫描发现的应用直接依赖),且报错 URL 不变。
|
|
523
|
+
此时改用 `resolve.alias` 把**引用方** `@formily/reactive-react` 指向它的 **CJS(`lib`)构建**——
|
|
524
|
+
CJS 用 `__importDefault(require('hoist-non-react-statics'))` 处理互操作,在包内自洽,不依赖
|
|
525
|
+
ESM default(`lib/observer.js` 即此类):
|
|
526
|
+
|
|
527
|
+
```ts
|
|
528
|
+
resolve: {
|
|
529
|
+
alias: {
|
|
530
|
+
'@formily/reactive-react': path.resolve(rootDir, 'node_modules/@formily/reactive-react/lib'),
|
|
531
|
+
},
|
|
532
|
+
},
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
> 判断 `optimizeDeps.include` 是否真不生效:重启后看 `.vite/deps/_metadata.json`,
|
|
536
|
+
> 若连 `@formily/reactive-react` 都未出现在 `optimized`——即 include 的条目一个都没进,
|
|
537
|
+
> 则确属 include 未生效,用上面的 `resolve.alias` 兜底必成。
|
|
538
|
+
> 注意:`import { createRequire } from 'node:module'` 这类 shim **在浏览器 dev 不可行**
|
|
539
|
+
> (`node:module` 浏览器端不存在),不要用。
|
|
540
|
+
|
|
541
|
+
- 判断是否生效:重启后看 `.vite/deps/_metadata.json`,`optimized` 里应出现
|
|
542
|
+
`hoist-non-react-statics`(或该包连同引用方一起被预打包)。
|
|
543
|
+
- 这是消费方运行时依赖问题,与 vite-config 无关,工厂不默认拦截;迁移后的页面应用遇到时按需加。
|
|
544
|
+
|
|
545
|
+
### 其它迁移期报错(oxc / lightningcss / 运行时全局)
|
|
546
|
+
|
|
547
|
+
- **`.js` 里写 JSX → `Unexpected JSX expression`**:Vite 8(rolldown)的 transform 由 **oxc**
|
|
548
|
+
接管,按扩展名推断语言,对 `.js` 不转译 JSX(webpack 靠 babel-loader)。`src/` 下含 JSX 的
|
|
549
|
+
`.js` 改名 `.jsx`;`node_modules` 里不可改的文件用自定义 `enforce: "pre"` 插件 + 从 `vite`
|
|
550
|
+
导入的 `transformWithOxc(code, id, { lang: "jsx", jsxRuntime: "automatic" })` 预转换。
|
|
551
|
+
- **老 CSS `*zoom` 等 IE hack → lightningcss 报错**:`vite.css.lightningcss = { errorRecovery: true }`
|
|
552
|
+
剥离并降级为 warning。
|
|
553
|
+
- **浏览器兼容目标与 webpack 不同**:Vite/Rolldown 默认 `build.target: "modules"`(约 ES2020),
|
|
554
|
+
CSS 走 lightningcss 目标一致;webpack 侧无 autoprefixer/browserslist(只 terser + css-minimizer)。
|
|
555
|
+
页面应用若需兼容低于 ES2020 的浏览器,显式 `vite.build.target` 与
|
|
556
|
+
`vite.css.lightningcss.targets`(或恢复 `postcss` + autoprefixer);webpack 没配则一般可忽略。
|
|
557
|
+
- **`import style from "./x.less"` → `MISSING_EXPORT "default"`**:Vite 的 `.less` 无默认导出;
|
|
558
|
+
`style` 未被使用则改副作用导入 `import "./x.less"`。
|
|
559
|
+
- **worker 入口 → `?url`**:`import X from "pdfjs-dist/build/pdf.worker.entry"` 在 Vite 下改为
|
|
560
|
+
`import X from "pdfjs-dist/build/pdf.worker.min.js?url"`。
|
|
561
|
+
- **动态路由 `import(/* @vite-ignore */"@" + path)`**:`@vite-ignore` 使 Vite 跳过分析,`@/` 在
|
|
562
|
+
运行时是浏览器无法解析的裸说明符;改用 `import.meta.glob("/src/**/*.{jsx,tsx}")` 预注册 +
|
|
563
|
+
resolver(或改标准 `import` / `lazy`)。
|
|
564
|
+
- **`const` 重赋值 → `ILLEGAL_REASSIGNMENT`**:Babel 降级 `var` 掩盖,Rolldown 保留 `const`;
|
|
565
|
+
改 `const`→`let`。
|
|
566
|
+
|
|
567
|
+
## 9. 验证
|
|
568
|
+
|
|
569
|
+
1. `pnpm dev`:页面打开、代理生效、多环境 config 生效(`window.globalConfig` 有值)。
|
|
570
|
+
2. `pnpm build`:产物 `dist/<hash>/` + 根 `dist/index.html` + `dist/hash.txt`;
|
|
571
|
+
config 复制到目标路径;svg 组件渲染正常;less 变量注入生效。
|
|
572
|
+
3. 产物挂静态服务,验证相对路径资源、hash 入口与回滚(`hashCleanup` 保留版本数)。
|
|
573
|
+
|
|
574
|
+
---
|
|
575
|
+
|
|
576
|
+
## 组件库(`createLibConfig` → `createLibraryViteConfig`)
|
|
577
|
+
|
|
578
|
+
面向当前使用 `createLibConfig`(**组件库 UMD 产物**)的组件包,切换到 `createLibraryViteConfig`
|
|
579
|
+
(`vite.config.ts`)。页面应用路径见上方 §1–§9;本节只讲组件库的差异。
|
|
580
|
+
|
|
581
|
+
与页面应用相比,组件库工厂**不启用 Hash 部署、public 复制、public-config**,`serve` 也不是站点,
|
|
582
|
+
而是本地预览应用;产物是库文件而非站点。完整工厂选项见
|
|
583
|
+
[API](./api.md#createlibraryviteconfigoptions)。
|
|
584
|
+
|
|
585
|
+
### 1. 依赖变更
|
|
586
|
+
|
|
587
|
+
```bash
|
|
588
|
+
pnpm add -D @hzab/vite-config vite@^8 @vitejs/plugin-react@^6 @vitejs/plugin-basic-ssl@^2 @rolldown/plugin-babel@^0.2 vite-plugin-html@^3 vite-plugin-static-copy@^4
|
|
589
|
+
|
|
590
|
+
# 启用 svg 组件通道(svgr)时另装可选 peer
|
|
591
|
+
pnpm add -D @svgr/core @svgr/plugin-jsx @svgr/plugin-svgo
|
|
592
|
+
|
|
593
|
+
# 删除 webpack 工具链
|
|
594
|
+
pnpm remove webpack webpack-cli webpack-dev-server
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
- 删除根 `webpack.config.js`;开发工具自声明(prettier / eslint / @typescript-eslint/* / husky /
|
|
598
|
+
lint-staged / typescript / cross-env)同样适用(见上方 §1 与 [webpack-config 迁移指南]
|
|
599
|
+
../../webpack-config/docs/migration.md 第 2 条)。
|
|
600
|
+
- `babel.config.js` 里的其它插件 / 预设(如 decorators)不再由 webpack-config 分发,需在
|
|
601
|
+
devDependencies 自声明。
|
|
602
|
+
- 组件库外置由 `createLibraryViteConfig` 负责,**不搬** webpack 的 `externals` 到 vite 同名
|
|
603
|
+
字段——vite 默认只外置 `react` / `react-dom`(含子路径 `react/jsx-runtime`),而 webpack 组件
|
|
604
|
+
构建默认外置的 `antd` / `@formily/*` / `@hzab/form-render` 需显式追加(`externals` 数组是**整表
|
|
605
|
+
替换**,追加要展开 `DEFAULT_LIBRARY_EXTERNALS`,见 §2)。
|
|
606
|
+
|
|
607
|
+
### 2. 新增根 `vite.config.ts`
|
|
608
|
+
|
|
609
|
+
```ts
|
|
610
|
+
import path from "node:path";
|
|
611
|
+
import { fileURLToPath } from "node:url";
|
|
612
|
+
import { defineConfig } from "vite";
|
|
613
|
+
import { createLibraryViteConfig, DEFAULT_LIBRARY_EXTERNALS } from "@hzab/vite-config";
|
|
614
|
+
|
|
615
|
+
const rootDir = path.dirname(fileURLToPath(import.meta.url));
|
|
616
|
+
|
|
617
|
+
export default defineConfig(({ command, mode }) =>
|
|
618
|
+
createLibraryViteConfig({
|
|
619
|
+
rootDir,
|
|
620
|
+
command,
|
|
621
|
+
mode,
|
|
622
|
+
name: "MyLib", // formats 含 umd / iife 的 build 必填(对齐 webpack output.library)
|
|
623
|
+
alias: {
|
|
624
|
+
"@": path.resolve(rootDir, "./src"),
|
|
625
|
+
// '@hzab/utils': path.resolve(rootDir, '../utils/src/index.ts'), // workspace 源码别名
|
|
626
|
+
},
|
|
627
|
+
// 追加外置:webpack 组件构建默认外置 antd / @formily/* / @hzab/form-render,这里显式列出
|
|
628
|
+
externals: [...DEFAULT_LIBRARY_EXTERNALS, "antd", "@formily/core", "@formily/react"],
|
|
629
|
+
// globals: { antd: 'antd' }, // UMD 全局名;未传时字符串 external 用自身包名
|
|
630
|
+
// previewHtml: 'example/index.html', // serve 预览模板;未传用根 index.html;不默认 example/
|
|
631
|
+
// reactCompiler: false, // 未装 babel-plugin-react-compiler 时关闭(默认 build-only)
|
|
632
|
+
// svgr: true, // 启用 import Icon from './x.svg?react';需可选 peer @svgr/*
|
|
633
|
+
// vite: { server: { port: 3000 } }, // 原 devServer.port(vite 默认 5173)
|
|
634
|
+
}),
|
|
635
|
+
);
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
> 组件库工厂 `serve` 是**预览应用**(走根 `index.html` 或 `previewHtml`),`build` 才是库产物;
|
|
639
|
+
> 不要用应用工厂的 `hashDeploy` 去包一层。`publicDir` 固定为 `false`,需要静态目录时经
|
|
640
|
+
> `vite.publicDir` 打开。
|
|
641
|
+
|
|
642
|
+
### 3. 配置项映射(`createLibConfig` → `createLibraryViteConfig`)
|
|
643
|
+
|
|
644
|
+
| webpack `createLibConfig` | `createLibraryViteConfig` | 说明 |
|
|
645
|
+
| ----------------------------------------------------------------------------- | -------------------------------------------- | -------------------------------------------------------------------------- |
|
|
646
|
+
| `output.library`(UMD 全局名) | `name` | `formats` 含 `umd` / `iife` 的 **build** 必填;未传会抛 `name is required` |
|
|
647
|
+
| `output.path` / `filename`(`componentsMode.prodOutput`) | `outDir` / `fileName` | 默认 `lib` / `index.js`(单一 format) |
|
|
648
|
+
| `componentsMode.prodEntry` | `entry` | 库入口,相对 `rootDir`;默认 `src/index.ts` |
|
|
649
|
+
| `componentsMode.localEntry`(example 入口) | 根 `index.html` + `previewHtml` | `serve` 是预览应用,不走 UMD;不默认 `example/` |
|
|
650
|
+
| 默认 externals(`react`/`react-dom`/`antd`/`@formily/*`/`@hzab/form-render`) | `externals` | vite 默认仅 `react` / `react-dom`,其余需显式追加(整表替换) |
|
|
651
|
+
| `resolve.alias` | `alias` | 不默认 `@` / `@assets` / `@service` |
|
|
652
|
+
| less-loader `javascriptEnabled`(webpack 恒 `true`) | `less` / `vite.css.preprocessorOptions.less` | 默认 `false`,formily 内联 JS 需显式开 |
|
|
653
|
+
| `svgrConf`(`?svgEle`) | `svgr`(`?react`) | query 契约不同,见 §4 |
|
|
654
|
+
| `isHash` / `writeHash` | 无对等 | 组件库 webpack 侧本就不写 Hash,vite 侧也没有 |
|
|
655
|
+
| `closeMulEnvConf` / public-config 复制 | 无对等 | 组件库不复制 public-config;需要时经 `vite.publicDir` |
|
|
656
|
+
|
|
657
|
+
### 4. 源码替换
|
|
658
|
+
|
|
659
|
+
- `import X from 'x.svg?svgEle'` → `import X from 'x.svg?react'`(并启用 `svgr`),两契约不兼容
|
|
660
|
+
(同页面应用 §4)。
|
|
661
|
+
- `process.env.WEBPACK_ENV` → `import.meta.env.MODE`;`process.env.WEBPACK_PUBLIC_PATH` →
|
|
662
|
+
打包资源用 `import.meta.env.BASE_URL`,根入口 `fetch` 用 `import.meta.env.PUBLIC_PATH`(同页面应用 §4)。
|
|
663
|
+
- 库代码若引用 `process.env.PACKAGE_VERSION`(webpack 侧注入的是 **webpack-config 自己**的版本),
|
|
664
|
+
改从组件库自身 `package.json` 读取并经 `vite.define` 注入(见页面应用 §4)。通常组件库不需要。
|
|
665
|
+
- `ProvidePlugin({ React })` 不需要:`@vitejs/plugin-react` 默认 automatic JSX runtime(同页面应用 §4)。
|
|
666
|
+
|
|
667
|
+
### 5. package.json scripts
|
|
668
|
+
|
|
669
|
+
```jsonc
|
|
670
|
+
{
|
|
671
|
+
"dev": "vite", // serve 预览应用(根 index.html / previewHtml)
|
|
672
|
+
"build": "vite build", // 产出 lib/ 库文件
|
|
673
|
+
"preview": "vite preview",
|
|
674
|
+
"typecheck": "tsc -b",
|
|
675
|
+
}
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
> **类型声明 `.d.ts`:`vite build`(lib) 不产 `d.ts`。** `build.lib` 只出 JS/CSS;组件包若需对外
|
|
679
|
+
> 发布类型(消费者 `import` 要有提示),得自己产——`tsc --emitDeclarationOnly`(配独立的
|
|
680
|
+
> `tsconfig.build.json`)或 `vite-plugin-dts`(经工厂 `plugins` 传入)。webpack 的 UMD 构建本
|
|
681
|
+
> 也不产 `d.ts`,但切换后别把这个步骤丢掉。
|
|
682
|
+
|
|
683
|
+
组件库 build 无多环境 public-config / Hash,不需要 `--mode` 多套;`mode` 也不据此切换库产物。
|
|
684
|
+
serve 预览端口默认 5173(vite 默认),用 `vite.server.port` 恢复 webpack 的 3000。
|
|
685
|
+
|
|
686
|
+
### 6. 入口与类型声明
|
|
687
|
+
|
|
688
|
+
- 新增根 `index.html`(serve 预览入口),或传 `previewHtml` 指向 `example/index.html`;`<%= PUBLIC_PATH %>`
|
|
689
|
+
由工厂注入仅对预览页生效。
|
|
690
|
+
- 新增 `src/vite-env.d.ts`:`/// <reference types="vite/client" />`。应用工厂另加
|
|
691
|
+
`/// <reference types="@hzab/vite-config/client" />`(见页面应用 §3);组件库预览一般不需要。
|
|
692
|
+
- svg 组件类型(三选一,见页面应用 §3):`/// <reference types="@hzab/vite-config/svg-react" />`,
|
|
693
|
+
或 tsconfig `types` 数组,或副作用导入。
|
|
694
|
+
|
|
695
|
+
### 7.(可选)Vitest 测试配置
|
|
696
|
+
|
|
697
|
+
组件库包单测用 `createPackageVitestConfig`(从 `@hzab/vite-config/vitest` 导入),同页面应用 §6。
|
|
698
|
+
组件包默认 `environment: "happy-dom"`(可选 peer,需装 `happy-dom`);纯逻辑包传 `environment: "node"`。
|
|
699
|
+
测试 import less 用 `stubLess: true` 桩掉,或 `vite.css.preprocessorOptions.less` 补齐 less 选项。
|
|
700
|
+
|
|
701
|
+
### 8. 已知差异 / 缺口
|
|
702
|
+
|
|
703
|
+
| 差异 | 说明 |
|
|
704
|
+
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
|
705
|
+
| serve 预览形态 | vite serve 不产 UMD,是预览应用;需根 `index.html` 或 `previewHtml`,**不**默认 `example/`(webpack `local` 默认 `./example/index.tsx`) |
|
|
706
|
+
| externals 默认更少 | webpack 外置 `antd` / `@formily/*` / `@hzab/form-render`;vite 默认仅 `react` / `react-dom`,需显式 `externals` 追加 |
|
|
707
|
+
| `output.library` 位置 | webpack 在 `output.library`;vite 是工厂 `name`(且仅为 UMD / IIFE 需要;`formats: ["es"]` 可省) |
|
|
708
|
+
| 多 format | webpack 单一 UMD;vite 默认 `["umd"]`,可用 `formats: ["es", "umd"]` 同时产 ESM + UMD |
|
|
709
|
+
| less `javascriptEnabled` 默认 false | 需显式开(同页面应用 §8) |
|
|
710
|
+
| svg query | `?svgEle` → `?react` |
|
|
711
|
+
| UMD 全局名 | `globals` 合并默认 react → `React`、react-dom → `ReactDOM`;字符串 external 的全局名默认取包名 |
|
|
712
|
+
| CSS 产物 | 库入口导入样式时写出 `lib/<cssFileName>.css`(默认 `index.css`) |
|
|
713
|
+
|
|
714
|
+
### 9. 验证
|
|
715
|
+
|
|
716
|
+
1. `pnpm dev`:预览应用打开(根 `index.html` / `previewHtml`),组件示例可交互。
|
|
717
|
+
2. `pnpm build`:产物 `lib/index.js`(+ 可选 `index.css`);检查 bundle 内**不含** externals
|
|
718
|
+
(`react` / `antd` 等)——即外置生效。
|
|
719
|
+
3. 发布前 `pnpm --filter <pkg> pack --dry-run` + 消费方装 tarball 后 import,确认 UMD / ESM 产物与
|
|
720
|
+
UMD 全局名(`window.<name>`)符合预期。
|
|
721
|
+
|
|
722
|
+
返回 [文档目录](./README.md)。
|