@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.
Files changed (151) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/LICENSE +21 -0
  3. package/README.md +173 -0
  4. package/dist/create-app-vite-config.cjs +426 -0
  5. package/dist/create-app-vite-config.cjs.map +1 -0
  6. package/dist/create-app-vite-config.d.cts +19 -0
  7. package/dist/create-app-vite-config.d.ts +19 -0
  8. package/dist/create-app-vite-config.js +415 -0
  9. package/dist/create-app-vite-config.js.map +1 -0
  10. package/dist/create-library-vite-config.cjs +281 -0
  11. package/dist/create-library-vite-config.cjs.map +1 -0
  12. package/dist/create-library-vite-config.d.cts +31 -0
  13. package/dist/create-library-vite-config.d.ts +31 -0
  14. package/dist/create-library-vite-config.js +268 -0
  15. package/dist/create-library-vite-config.js.map +1 -0
  16. package/dist/create-package-vitest-config.cjs +73 -0
  17. package/dist/create-package-vitest-config.cjs.map +1 -0
  18. package/dist/create-package-vitest-config.d.cts +12 -0
  19. package/dist/create-package-vitest-config.d.ts +12 -0
  20. package/dist/create-package-vitest-config.js +67 -0
  21. package/dist/create-package-vitest-config.js.map +1 -0
  22. package/dist/create-vite-config.cjs +438 -0
  23. package/dist/create-vite-config.cjs.map +1 -0
  24. package/dist/create-vite-config.d.cts +17 -0
  25. package/dist/create-vite-config.d.ts +17 -0
  26. package/dist/create-vite-config.js +427 -0
  27. package/dist/create-vite-config.js.map +1 -0
  28. package/dist/index.cjs +631 -0
  29. package/dist/index.cjs.map +1 -0
  30. package/dist/index.d.cts +16 -0
  31. package/dist/index.d.ts +16 -0
  32. package/dist/index.js +603 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/plugins/copy.cjs +16 -0
  35. package/dist/plugins/copy.cjs.map +1 -0
  36. package/dist/plugins/copy.d.cts +18 -0
  37. package/dist/plugins/copy.d.ts +18 -0
  38. package/dist/plugins/copy.js +13 -0
  39. package/dist/plugins/copy.js.map +1 -0
  40. package/dist/plugins/hash-deploy.cjs +128 -0
  41. package/dist/plugins/hash-deploy.cjs.map +1 -0
  42. package/dist/plugins/hash-deploy.d.cts +56 -0
  43. package/dist/plugins/hash-deploy.d.ts +56 -0
  44. package/dist/plugins/hash-deploy.js +119 -0
  45. package/dist/plugins/hash-deploy.js.map +1 -0
  46. package/dist/plugins/less-tilde.cjs +32 -0
  47. package/dist/plugins/less-tilde.cjs.map +1 -0
  48. package/dist/plugins/less-tilde.d.cts +36 -0
  49. package/dist/plugins/less-tilde.d.ts +36 -0
  50. package/dist/plugins/less-tilde.js +29 -0
  51. package/dist/plugins/less-tilde.js.map +1 -0
  52. package/dist/plugins/lifecycle.cjs +28 -0
  53. package/dist/plugins/lifecycle.cjs.map +1 -0
  54. package/dist/plugins/lifecycle.d.cts +20 -0
  55. package/dist/plugins/lifecycle.d.ts +20 -0
  56. package/dist/plugins/lifecycle.js +26 -0
  57. package/dist/plugins/lifecycle.js.map +1 -0
  58. package/dist/plugins/public-assets.cjs +28 -0
  59. package/dist/plugins/public-assets.cjs.map +1 -0
  60. package/dist/plugins/public-assets.d.cts +17 -0
  61. package/dist/plugins/public-assets.d.ts +17 -0
  62. package/dist/plugins/public-assets.js +26 -0
  63. package/dist/plugins/public-assets.js.map +1 -0
  64. package/dist/plugins/public-config.cjs +31 -0
  65. package/dist/plugins/public-config.cjs.map +1 -0
  66. package/dist/plugins/public-config.d.cts +20 -0
  67. package/dist/plugins/public-config.d.ts +20 -0
  68. package/dist/plugins/public-config.js +29 -0
  69. package/dist/plugins/public-config.js.map +1 -0
  70. package/dist/plugins/react-compiler.cjs +22 -0
  71. package/dist/plugins/react-compiler.cjs.map +1 -0
  72. package/dist/plugins/react-compiler.d.cts +24 -0
  73. package/dist/plugins/react-compiler.d.ts +24 -0
  74. package/dist/plugins/react-compiler.js +16 -0
  75. package/dist/plugins/react-compiler.js.map +1 -0
  76. package/dist/plugins/relative-base.cjs +19 -0
  77. package/dist/plugins/relative-base.cjs.map +1 -0
  78. package/dist/plugins/relative-base.d.cts +9 -0
  79. package/dist/plugins/relative-base.d.ts +9 -0
  80. package/dist/plugins/relative-base.js +17 -0
  81. package/dist/plugins/relative-base.js.map +1 -0
  82. package/dist/plugins/stub-less.cjs +26 -0
  83. package/dist/plugins/stub-less.cjs.map +1 -0
  84. package/dist/plugins/stub-less.d.cts +9 -0
  85. package/dist/plugins/stub-less.d.ts +9 -0
  86. package/dist/plugins/stub-less.js +24 -0
  87. package/dist/plugins/stub-less.js.map +1 -0
  88. package/dist/plugins/svg-react.cjs +70 -0
  89. package/dist/plugins/svg-react.cjs.map +1 -0
  90. package/dist/plugins/svg-react.d.cts +28 -0
  91. package/dist/plugins/svg-react.d.ts +28 -0
  92. package/dist/plugins/svg-react.js +63 -0
  93. package/dist/plugins/svg-react.js.map +1 -0
  94. package/dist/svg-react-runtime.cjs +4 -0
  95. package/dist/svg-react-runtime.cjs.map +1 -0
  96. package/dist/svg-react-runtime.d.cts +2 -0
  97. package/dist/svg-react-runtime.d.ts +2 -0
  98. package/dist/svg-react-runtime.js +3 -0
  99. package/dist/svg-react-runtime.js.map +1 -0
  100. package/dist/types.cjs +4 -0
  101. package/dist/types.cjs.map +1 -0
  102. package/dist/types.d.cts +291 -0
  103. package/dist/types.d.ts +291 -0
  104. package/dist/types.js +3 -0
  105. package/dist/types.js.map +1 -0
  106. package/dist/vitest-types.cjs +4 -0
  107. package/dist/vitest-types.cjs.map +1 -0
  108. package/dist/vitest-types.d.cts +22 -0
  109. package/dist/vitest-types.d.ts +22 -0
  110. package/dist/vitest-types.js +3 -0
  111. package/dist/vitest-types.js.map +1 -0
  112. package/dist/vitest.cjs +73 -0
  113. package/dist/vitest.cjs.map +1 -0
  114. package/dist/vitest.d.cts +4 -0
  115. package/dist/vitest.d.ts +4 -0
  116. package/dist/vitest.js +67 -0
  117. package/dist/vitest.js.map +1 -0
  118. package/docs/README.md +15 -0
  119. package/docs/abt-management-ui/vite.config.mts +226 -0
  120. package/docs/api.md +366 -0
  121. package/docs/migration-from-webpack.md +722 -0
  122. package/docs/sync-public-path.md +52 -0
  123. package/docs/vite-config-integration.md +476 -0
  124. package/docs/vite-pnpm-integration.md +279 -0
  125. package/docs/vs-ccc-vite-config.md +26 -0
  126. package/docs/webpack-gap.md +107 -0
  127. package/package.json +113 -0
  128. package/src/client.d.ts +9 -0
  129. package/src/create-app-vite-config.ts +218 -0
  130. package/src/create-library-vite-config.ts +199 -0
  131. package/src/create-package-vitest-config.ts +54 -0
  132. package/src/create-vite-config.ts +22 -0
  133. package/src/index.ts +42 -0
  134. package/src/plugins/copy.ts +25 -0
  135. package/src/plugins/hash-deploy.ts +199 -0
  136. package/src/plugins/less-tilde.ts +44 -0
  137. package/src/plugins/lifecycle.ts +40 -0
  138. package/src/plugins/public-assets.ts +28 -0
  139. package/src/plugins/public-config.ts +34 -0
  140. package/src/plugins/react-compiler.ts +32 -0
  141. package/src/plugins/relative-base.ts +20 -0
  142. package/src/plugins/stub-less.ts +26 -0
  143. package/src/plugins/svg-react.ts +90 -0
  144. package/src/svg-react-runtime.ts +4 -0
  145. package/src/svg-react.d.ts +6 -0
  146. package/src/types.ts +314 -0
  147. package/src/vitest-types.ts +20 -0
  148. package/src/vitest.ts +2 -0
  149. package/templates/src/vite-env.d.ts +2 -0
  150. package/templates/tsconfig.json +12 -0
  151. package/templates/vite.config.ts +26 -0
@@ -0,0 +1,52 @@
1
+ # 已实施:从 Vite 仓回灌 `PUBLIC_PATH` / `./client`
2
+
3
+ > 状态:**已实施**(2026-08-28)。
4
+ > 源:`~/Workbench/Vite/monorepo-packages/tooling/vite-config`(`@ccc/vite-config`)。
5
+ > 对照现状见 [vs-ccc-vite-config.md](./vs-ccc-vite-config.md)。
6
+
7
+ 工厂在 `configure` 之后写入 `import.meta.env.PUBLIC_PATH`,供根入口 JS `fetch` / 动态 URL。相对 Hash 必须用 `./{hash}/`,不能跟 Vite `base`(后者保持 `./`)。HTML 子目录模板里的 `PUBLIC_PATH` 仍为 `./`,与 JS 前缀不是同一个值。
8
+
9
+ 包名保持 `@hzab/vite-config`。本仓引号与对照仓一致(双引号)。单独 changeset / 发版。
10
+
11
+ ## 已落地
12
+
13
+ 1. `applyJsPublicPathDefine` / `resolveJsPublicPath`:`configure` 之后写入 `import.meta.env.PUBLIC_PATH`
14
+ 2. `src/client.d.ts` 与 `exports["./client"]`
15
+ 3. `test/js-public-path.test.ts`
16
+ 4. 模板 `templates/src/vite-env.d.ts` 增加 `/// <reference types="@hzab/vite-config/client" />`
17
+ 5. 文档:JS `PUBLIC_PATH` vs HTML `PUBLIC_PATH` vs `BASE_URL`
18
+ 6. 重写 [vs-ccc-vite-config.md](./vs-ccc-vite-config.md)
19
+ 7. `typecheck` / `test` / `api-report` / `pnpm --filter @hzab/vite-config pack --dry-run`
20
+
21
+ ## 移植清单(对照)
22
+
23
+ | 源(Vite 仓) | 本仓动作 |
24
+ | --- | --- |
25
+ | `src/create-app-vite-config.ts` | 已拷 `JS_PUBLIC_PATH_DEFINE_KEY`、`ensureTrailingSlash`、`resolveJsPublicPath`、`applyJsPublicPathDefine`;`configure` 之后调用 |
26
+ | `src/client.d.ts` | 已拷;声明 `ImportMetaEnv.PUBLIC_PATH` |
27
+ | `package.json` `exports["./client"]` | `{ "types": "./src/client.d.ts" }` |
28
+ | `test/js-public-path.test.ts` | 已拷;另断言 `./client` 为仅 types |
29
+ | `templates/src/vite-env.d.ts` | 已加 `/// <reference types="@hzab/vite-config/client" />` |
30
+ | `docs/api.md` / README | JS `import.meta.env.PUBLIC_PATH` vs HTML `<%= PUBLIC_PATH %>` vs `BASE_URL` |
31
+ | `src/types.ts` `htmlData` | 已注明 JS 用 `import.meta.env.PUBLIC_PATH` |
32
+
33
+ 消费方必须写成静态成员 `import.meta.env.PUBLIC_PATH`,不要解构。`vite.define` / `configure` 里的同名键会被工厂覆盖。
34
+
35
+ ## 刻意不搬
36
+
37
+ | 项 | 原因 |
38
+ | --- | --- |
39
+ | `catalog:` | 本仓钉死版本 |
40
+ | `release.config.json` | 本仓走 `publish-target.json` |
41
+ | 改包名为 `@ccc` | scope 即仓身份 |
42
+
43
+ ## 验证
44
+
45
+ ```bash
46
+ pnpm --filter @hzab/vite-config typecheck
47
+ pnpm --filter @hzab/vite-config test
48
+ pnpm --filter @hzab/vite-config api-report
49
+ pnpm --filter @hzab/vite-config pack --dry-run
50
+ ```
51
+
52
+ 确认 `exports` 含 `./client`(仅 types)与既有 `./svg-react` runtime。默认入口仍是 `dist/`。
@@ -0,0 +1,476 @@
1
+ # abt-management-ui 接入 `@hzab/vite-config` 记录
2
+
3
+ > 本文记录本项目(`abt-management-ui`)从 **webpack5 + `@hzab/webpack-config`** 迁移到 **Vite 8(rolldown)+ `@hzab/vite-config`** 的完整落地过程:环境准备、依赖安装、`vite.config.mts` 编排、`index.html` 模板化,以及迁移中实际踩到的坑与修复。
4
+ >
5
+ > 通用排查方法论(现象 → 根因 → 诊断 → 修复)见 [Vite + pnpm 接入排障手册](./vite-pnpm-integration.md);本文聚焦**本项目从 0 到 1 的接入步骤**,两篇配合阅读。
6
+
7
+ ---
8
+
9
+ ## 0. 背景与目标
10
+
11
+ | 维度 | 迁移前(webpack5) | 迁移后(Vite 8 / rolldown) |
12
+ | --------- | --------------------------------------------------------------------- | ----------------------------------------------------------------- |
13
+ | 配置入口 | `config/webpack.config.js`(`@hzab/webpack-config` 的 `mergeConfig`) | `vite.config.mts`(`@hzab/vite-config` 的 `createAppViteConfig`) |
14
+ | HTML 模板 | webpack HtmlWebpackPlugin 模板 | `index.html` + `vite-plugin-html`(EJS) |
15
+ | 入口 | `./src/index.jsx` | 同左(`index.html` 引用 `/src/index.jsx`) |
16
+ | 包管理器 | 原以 npm/yarn 为主 | **pnpm**(workspace + 严格隔离) |
17
+ | 目标 | —— | dev / 生产构建正常,补全 `@hzab/*` 源码包与旧 CJS 依赖兼容 |
18
+
19
+ **迁移核心矛盾**:本项目批量依赖 `@hzab/*` 系列源码包(`main` 指向 `src`,由 Vite 直接编译),且依赖较多旧 CJS 包。pnpm 的严格隔离布局不会把这些依赖提升到顶层 `node_modules`,Vite 的 `optimizeDeps` 预构建发现不了它们,只能按原始 CJS 裸供浏览器 —— 这是绝大多数报错的统一根因(详见排障手册 §0 / §1)。
20
+
21
+ ---
22
+
23
+ ## 1. 环境要求
24
+
25
+ ```text
26
+ Node.js >= 24 // @hzab/vite-config 引擎要求
27
+ pnpm // 本仓库使用 pnpm workspace
28
+ vite ^8.2.2 // rolldown 版
29
+ ```
30
+
31
+ 本项目当前环境:`node v24.18.0`。
32
+
33
+ ---
34
+
35
+ ## 2. 依赖清单
36
+
37
+ ### 2.1 新增 devDependencies(Vite 相关 + 接入包)
38
+
39
+ ```jsonc
40
+ // package.json devDependencies 增量(摘录)
41
+ "@hzab/vite-config": "0.0.2-alpha.0", // 配置工厂
42
+ "vite": "^8.2.2",
43
+ "@vitejs/plugin-react": "^6.1.0",
44
+ "@vitejs/plugin-basic-ssl": "^2.3.0",
45
+ "@rolldown/plugin-babel": "~0.2.3",
46
+ "vite-plugin-html": "^3.2.2",
47
+ "vite-plugin-static-copy": "^4.1.1",
48
+ "@originjs/vite-plugin-commonjs": "^1.0.3", // CJS 转换
49
+ "vite-plugin-commonjs": "^0.10.4"
50
+ ```
51
+
52
+ ### 2.2 新增 dependencies(为兼容 CJS 提升的共享老包)
53
+
54
+ > 这些包是 CJS-only 的**共享/传递依赖**,pnpm 不会把它们提升到顶层。为了能被根解析并触发 `optimizeDeps` 预构建,**必须提升为直接依赖**(详见排障手册 §4.2)。
55
+
56
+ ```jsonc
57
+ "react-is": "16.13.1", // module is not defined
58
+ "deep-equal": "1.1.2", // require is not defined(es-shims 闭包入口)
59
+ "geojson-equality": "0.1.6" // require is not defined(同经 deep-equal)
60
+ ```
61
+
62
+ ### 2.3 peer 依赖(`@hzab/vite-config` 声明,多数由上方 devDependencies 覆盖)
63
+
64
+ ```text
65
+ vite、@vitejs/plugin-react、@vitejs/plugin-basic-ssl、@rolldown/plugin-babel、
66
+ vite-plugin-html、vite-plugin-static-copy
67
+ ```
68
+
69
+ > ⚠️ **可选 peer `@svgr/*` 当前未安装**(见 §7 遗留事项):本项目已在 `vite.config.mts` 开启 `svgr: true`,但 `@svgr/core`、`@svgr/plugin-jsx`(svgo 默认开启还需 `@svgr/plugin-svgo`)不在依赖清单中。若用到 `import Icon from "./icon.svg?react"`,需先补装。
70
+
71
+ ### 2.4 代码规范提交钩子(husky + lint-staged)
72
+
73
+ 提交前格式化依赖的整套工具链,**`lint-staged` 必须列为 `devDependencies`**:
74
+
75
+ - `husky`(`^8.0.3`):`package.json` 的 `prepare: husky install` 会在安装后写好 git 钩子;`.husky/pre-commit` 在 commit 前执行 `npx lint-staged`。
76
+ - `lint-staged`(`^13.2.3`):预检脚本里被 `npx` 调用的命令。**只要它不明确列入 `devDependencies`,`pnpm install` 就不会把它链接到顶层 `node_modules/.bin`**(它只是某依赖的传递依赖),于是 `npx lint-staged` 找不到命令,`git commit` 会被 pre-commit 钩子以退出码 1 截断(见 §4.10)。配置在 `package.json` 顶层 `lint-staged` 字段:对暂存的 `**.{js,jsx,ts,tsx,css,scss,less,json,html}` 执行 `prettier --write`。
77
+ - `prettier`(`2.8.7`):lint-staged 的格式化命令依赖,需在 `devDependencies`。
78
+
79
+ ---
80
+
81
+ ## 3. 接入步骤
82
+
83
+ ### 3.1 安装依赖
84
+
85
+ ```bash
86
+ pnpm install
87
+ ```
88
+
89
+ > 若手动新增依赖可:`pnpm add @hzab/vite-config -D`,其余按 2.1 / 2.2 清单补装。迁移涉及的直接依赖(`react-is` 等)需要 `pnpm add <pkg>` 以便提升到顶层。
90
+
91
+ ### 3.2 新建 `vite.config.mts`,用 `createAppViteConfig` 编排
92
+
93
+ 入口是 `defineConfig(({ command, mode }) => createAppViteConfig({ ... }))`。完整文件(含注释)见项目根 `vite.config.mts`。核心结构如下——注意模块顶部会**读取 `package.json` 版本号**注入 `PACKAGE_VERSION` / `APP_VERSION`,并定义若干**解析函数**(`resolveCFormilyAntdEsm` / `resolveTurfJstsEsm` / `resolveQuickselectEsm` / `resolveClassnamesUtilsSrc`,见 §4.3)与一个 **`.js` 里写 JSX 的预转换插件** `jsxInJsPlugin`(见 §4.9):
94
+
95
+ ```ts
96
+ import fs from "node:fs";
97
+ import path from "node:path";
98
+ import { fileURLToPath } from "node:url";
99
+ import { defineConfig, transformWithOxc } from "vite";
100
+ import { viteCommonjs } from "@originjs/vite-plugin-commonjs";
101
+ import { createAppViteConfig } from "@hzab/vite-config";
102
+
103
+ const rootDir = path.dirname(fileURLToPath(import.meta.url));
104
+
105
+ // 读取 package.json 版本号,注入 process.env.PACKAGE_VERSION / process.env.APP_VERSION,
106
+ // 对齐 @hzab/webpack-config 的 DefinePlugin 默认注入(webpack 侧会暴露 PACKAGE_VERSION)
107
+ const pkgJson = JSON.parse(fs.readFileSync(path.resolve(rootDir, "package.json"), "utf8"));
108
+ const PACKAGE_VERSION = pkgJson.version || "";
109
+
110
+ // .js 里写 JSX 的预转换插件:Vite 8 (rolldown) 由 oxc 接管 transform,
111
+ // 默认对 .js 不解析 JSX 会报 "Unexpected JSX expression"(含 node_modules 内不可改的来源包)
112
+ const jsxInJsPlugin = {/* ...见 §4.9... */};
113
+
114
+ export default defineConfig(({ command, mode }) =>
115
+ createAppViteConfig({
116
+ rootDir,
117
+ command,
118
+ mode,
119
+ // alias 覆盖:@packages/@assets/@service 为原 resolve.alias;hzab-schema-* 对齐旧 webpack alias;
120
+ // 其余为 JSX/UMD/CJS 已知兼容改写(c-formily-antd、turf-jsts、quickselect、@hzab/classnames-utils),见 §4.3
121
+ alias: {
122
+ "@": path.resolve(rootDir, "./src"),
123
+ "@assets": path.resolve(rootDir, "./src/assets"),
124
+ "@packages": path.resolve(rootDir, "./packages"),
125
+ "hzab-schema-form-render": path.resolve(rootDir, "packages/pc/form-render"),
126
+ "hzab-schema-list-render": path.resolve(rootDir, "packages/pc/list-render"),
127
+ // ... 已知别名覆盖见 §4.3
128
+ },
129
+ devProxy: { "/api": "http://localhost:13000" },
130
+ less: { javascriptEnabled: true, resolveTilde: true }, // formily 内联 JS 才需要;~ 解析默认关闭
131
+ hashDeploy: mode !== "development",
132
+ hashTimestamp: "datetime", // hash 子目录名时间戳:YYYY-MM-DD-HH-mm-ss(默认 epoch 毫秒)
133
+ hashCleanup: { keep: 3 }, // 可选;缺省永久保留旧版本
134
+ publicConfig: { mode: process.env.PUBLIC_CONF_DIR || mode, dest: "public/config" }, // glob 键优先 PUBLIC_CONF_DIR(对齐 webpack 多环境目录),未设置回退 mode;默认产物 config/
135
+ htmlData: { APP_TITLE: "My App" }, // 仅 PUBLIC_PATH 由工厂始终注入,其余键必须在此声明
136
+ svgr: true, // 启用 svg 组件通道,import 需由 ?svgEle 改为 ?react
137
+ reactCompiler: false, // babel-plugin-react-compiler 未安装,build-only 会失败
138
+ plugins: [jsxInJsPlugin, viteCommonjs({ include: [/* ...见下 */] })],
139
+ vite: {
140
+ server: { port: 3000 },
141
+ css: { lightningcss: { errorRecovery: true } }, // 剥离老 IE *zoom 等 hack,避免中断构建
142
+ optimizeDeps: { include: ["react-is", "deep-equal", "geojson-equality"] },
143
+ define: {/* process.env.* 注入,见 §4.8 */},
144
+ },
145
+ }),
146
+ );
147
+ ```
148
+
149
+ > `viteCommonjs.include` 为可选,显式指定需转换的包名(本项目:`classnames`、`dayjs`、`rbush`、`earcut`、`skmeans`、`turf-jsts`、`polygon-clipping`、`density-clustering`、`point-in-polygon`、`object-assign`、`hoist-non-react-statics`、`prop-types`)。注意**不要用它去救「具名导出」**——它只能产出 `default` 导出(见排障手册 §5.6)。
150
+
151
+ ### 3.3 配置项映射(`config/webpack.config.js` → `vite.config.mts`)
152
+
153
+ | webpack 侧 | `@hzab/vite-config` 侧 | 本项目取值 |
154
+ | ------------------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
155
+ | `resolve.alias` | `alias` | `@` / `@assets` / `@packages`、`hzab-schema-form-render` / `hzab-schema-list-render`(→ `packages/pc/form-render` / `packages/pc/list-render`);其余为已知兼容改写(见 §4.3) |
156
+ | `devServer.proxy` | `devProxy` | `"/api": "http://localhost:13000"` |
157
+ | `devServer.port` | `vite.server.port` | `3000` |
158
+ | less-loader `additionalData` / `modifyVars` | `less` | `javascriptEnabled: true`(formily 内联 JS 需要)、`resolveTilde: true`(`~antd`;默认关闭) |
159
+ | `isHash` + hashPublicPath | `hashDeploy` / `base` | `hashDeploy: mode !== "development"`,另加 `hashTimestamp: "datetime"`;所有 build 脚本均 `--mode production` 使 hash 恒生效 |
160
+ | (旧版本保留数) | `hashCleanup` | `{ keep: 3 }`(可选;缺省永久保留) |
161
+ | `closeMulEnvConf` + public-config | `publicConfig` | `{ mode: process.env.PUBLIC_CONF_DIR | | mode, dest: "public/config" }`(glob 键优先 `PUBLIC_CONF_DIR`,未设置回退 `mode`;默认产物 `config/`) |
162
+ | `processEnv` / DefinePlugin | `vite.define` 注入 `process.env.*` + `index.html` 全局 `process` polyfill | 见 §4.8 `process is not defined`(含 `PACKAGE_VERSION` / `APP_VERSION` 来源) |
163
+ | HTML 模板数据 | `htmlData`(与内置 `PUBLIC_PATH` 合并) | `APP_TITLE` |
164
+ | `beforeBuild()` 复制 routes | `onRun`(`command === "build"` 时可用) | 未迁移(见 §7) |
165
+
166
+ > `PUBLIC_PATH` 由工厂按 `base` / Hash 自动计算并**始终注入**模板;`htmlData` 里同名键会被覆盖。除 `PUBLIC_PATH` 外,模板用到的其余 `htmlData` 键必须在此显式声明,否则取不到。
167
+
168
+ ### 3.4 `index.html` 模板化(webpack → vite-plugin-html EJS)
169
+
170
+ - `favicon` / 静态资源引用改为 `<%= PUBLIC_PATH %>...`。
171
+ - 注入的业务数据用 `<%= process.env.BUSINESS_PLATFORM %>` / `<%= process.env.NODE_ENV %>`。
172
+ - 入口脚本改为 `<script type="module" src="/src/index.jsx"></script>`。
173
+ - Cesium 相关 `<link>` / `<script>` 仍保留,路径按 `PUBLIC_PATH` 前缀。
174
+
175
+ ```html
176
+ <link rel="shortcut icon" href="<%= PUBLIC_PATH %>public/images/logo.png" />
177
+ <script>
178
+ window.__ENV = {
179
+ BUSINESS_PLATFORM: "<%= process.env.BUSINESS_PLATFORM %>",
180
+ NODE_ENV: "<%= process.env.NODE_ENV %>",
181
+ };
182
+ </script>
183
+ <script type="text/javascript" src="<%= PUBLIC_PATH %>public/config/config.js"></script>
184
+ <script type="module" src="/src/index.jsx"></script>
185
+ ```
186
+
187
+ ### 3.5 补类型声明 `src/vite-env.d.ts`
188
+
189
+ ```ts
190
+ /// <reference types="vite/client" />
191
+ /// <reference types="@hzab/vite-config/svg-react" />
192
+ ```
193
+
194
+ > `@hzab/vite-config/svg-react` 是纯类型入口;也可改用 tsconfig `compilerOptions.types` 数组(见包 README)。本项目采用 `src/vite-env.d.ts` 三斜线引用方式。
195
+
196
+ ### 3.6 改造 webpack 语法 → Vite 风格
197
+
198
+ 典型如 `src/package/anbao-router/index.tsx`:把无法在 Vite 下解析的写法改为标准 import.meta.glob
199
+
200
+ ```tsx
201
+ import React, { ReactNode, Suspense, lazy, ComponentType } from "react";
202
+
203
+ const pageModules = import.meta.glob<{ default: ComponentType<any> }>("/src/**/*.{jsx,tsx}");
204
+ // 现在 pageModules[fullPath] 的类型是 () => Promise<{ default: ComponentType<any> }>
205
+
206
+ // 路由配置里的 component 为相对 src 的路径,可能带或不带扩展名(如 "pages/home-page"),
207
+ // 这里补全为 import.meta.glob 产物的真实文件路径 key。
208
+ function resolveComponent(component: string): any {
209
+ const c = String(component)
210
+ .replace(/^@\//, "")
211
+ .replace(/^\.?\//, "")
212
+ .replace(/\\/g, "/");
213
+ const base = `/src/${c}`;
214
+ const candidates = [
215
+ base,
216
+ `${base}.jsx`,
217
+ `${base}.tsx`,
218
+ `${base}/index.jsx`,
219
+ `${base}/index.tsx`,
220
+ `${base}/index.js`,
221
+ ];
222
+ for (const key of candidates) {
223
+ if (pageModules[key]) return pageModules[key];
224
+ }
225
+ // 兜底:精确前缀匹配(如 component 指向目录下的其它文件)
226
+ const matched = Object.keys(pageModules).find((k) => k.startsWith(`${base}/`));
227
+ return matched ? pageModules[matched] : undefined;
228
+ }
229
+
230
+ // 使用
231
+ const loader = resolveComponent(routeObj.component);
232
+ const Module = lazy(() =>
233
+ loader
234
+ ? loader()
235
+ : Promise.reject(new Error(`[syncRouter] 未找到路由组件:${routeObj.component}`)),
236
+ );
237
+ ```
238
+
239
+ ### 3.7 调整 `package.json` scripts
240
+
241
+ 保留业务平台/环境变量注入,改用 `cross-env` + `vite`;`vite-plugin-html` 模板需要 `BUSINESS_PLATFORM` 等环境变量参与渲染:
242
+
243
+ ```jsonc
244
+ "dev": "cross-env BUSINESS_PLATFORM=abt PUBLIC_CONF_DIR=local vite --mode development",
245
+ "build-flow_dev": "cross-env BUSINESS_PLATFORM=abt PUBLIC_CONF_DIR=development vite build --mode production",
246
+ "build-flow_dev_tenant": "cross-env BUSINESS_PLATFORM=abt PUBLIC_CONF_DIR=dev_tenant vite build --mode production",
247
+ "build": "cross-env BUSINESS_PLATFORM=abt vite build --mode production",
248
+ "build-flow_dev:dbt": "cross-env BUSINESS_PLATFORM=dbt PUBLIC_CONF_DIR=dbt-development vite build --mode production",
249
+ "build:dbt": "cross-env BUSINESS_PLATFORM=dbt PUBLIC_CONF_DIR=dbt-production vite build --mode production"
250
+ ```
251
+
252
+ > 所有 `*build*` 脚本统一用 `--mode production`:`@hzab/vite-config` 的 hash 部署在 `mode === "development"` 时被强制关闭(工厂内 `isHash = isBuild && hashDeploy && mode !== "development"`),因此**要让每个 build 都出 hash,不能再用 `--mode development`**。开发服务器脚本(`dev` / `dev:dbt` 用 `vite` 而非 `vite build`)维持 development 模式、不出 hash,符合预期。
253
+ >
254
+ > `publicConfig` 的配置目录选择改为 `PUBLIC_CONF_DIR || mode`:各公共配置目录名与 `PUBLIC_CONF_DIR` 一一对应(`development` / `production` / `dev_tenant` / `dbt-development` / `dbt-production` / `local` / `dbt-local`)。这样切换 Vite `mode` 不影响按环境选配置(`build-flow_dev` → `development/*` 测试 API、`build-flow_dev:dbt` → `dbt-development/*` dbt 测试 API、`build:dbt` → `dbt-production/*` dbt 生产 API 等)。
255
+
256
+ ### 3.8 pnpm workspace / 构建许可
257
+
258
+ `pnpm-workspace.yaml` 声明了构建设置及私服 alpha 包放行:
259
+
260
+ ```yaml
261
+ allowBuilds:
262
+ "@parcel/watcher": false
263
+ canvas: true
264
+ es5-ext: true
265
+ esbuild: true
266
+ protobufjs: true
267
+ minimumReleaseAgeExclude:
268
+ - "@hzab/vite-config@0.0.2-alpha.0"
269
+ ```
270
+
271
+ > `minimumReleaseAgeExclude`:pnpm 默认会拦截 `minimumReleaseAge` 内、发布过久的包;这里放行 `@hzab/vite-config@0.0.2-alpha.0`,否则 `pnpm install` 会因该包发布时长不符合门槛而失败。
272
+
273
+ ---
274
+
275
+ ## 4. 问题修复记录
276
+
277
+ > 每个问题的**根因 / 诊断方法**详见排障手册对应章节;下表按本项目实际落地顺序记录「现象 → 采取的修复」。对应改动均落在 `vite.config.mts`、`package.json`、`pnpm-lock.yaml`。
278
+
279
+ ### 4.1 模块被 CJS 裸供 → `module is not defined`
280
+
281
+ - **现象**:浏览器 `Uncaught ReferenceError: module is not defined`。
282
+ - **根因**:CJS-only 包未被提升到顶层、未被预构建,`module.exports = require(...)` 直接下发给浏览器。
283
+ - **修复**(排障手册 §4.2):把 `react-is@16.13.1` 提升为直接依赖 + `pnpm install`,并加入 `optimizeDeps.include`。
284
+
285
+ ### 4.2 es-shims 闭包裸供 → `require is not defined`
286
+
287
+ - **现象**:`require is not defined`,报错的是 `object-keys`、`regexp.prototype.flags`、`define-properties` 等叶子包。
288
+ - **根因**:它们的**父入口包**(`deep-equal` / `geojson-equality`)被 `viteCommonjs.include` 转换后,其 CJS 依赖被逐个独立裸供。
289
+ - **修复**(排障手册 §4.2):**提升入口包**(`deep-equal`、`geojson-equality`)为直接依赖 + `optimizeDeps.include`,让预构建把整个 es-shims 闭包内联成一个 ESM 文件;同时**把入口包从 `viteCommonjs.include` 移除**,避免被二次转换。
290
+
291
+ ### 4.3 具名导出丢失 → `does not provide an export named 'X'`
292
+
293
+ | 包 | 现象 | 修复 | 依据 |
294
+ | ----------------------------------------------------------------- | ------------------------------- | -------------------------------------------------------------- | ------------- |
295
+ | `c-formily-antd@2.3.1`(仅 CJS 实例) | `useFormLayout` 等具名导出丢失 | alias 改写到一个带 `esm/` 的 2.3.5 实例,走原生 ESM `export *` | 排障手册 §4.1 |
296
+ | `turf-jsts`(`@turf/buffer` 的传递依赖) | `BufferOp` 具名导出丢失 | alias 到原生 ESM `jsts.mjs` | 排障手册 §4.1 |
297
+ | `@hzab/classnames-utils@0.0.2`(webpack 打的 UMD CJS,无 `esm/`) | `NO_PREFIX_TYPE` 等具名导出丢失 | alias 到其原生 TS ESM 源 `src/index.ts` | 排障手册 §4.1 |
298
+
299
+ > `@hzab/classnames-utils` 的 `lib/index.js` 是 webpack 打的 UMD bundle(`module.exports = t()`,用 `e.d` getter 定义具名导出),Vite 的 cjs 静态分析识别不出,故报 `does not provide an export named 'NO_PREFIX_TYPE'`。其 `src/`(`index.ts` / `ClassNameUtils.ts`)是干净的原生 TS ESM(`export const NO_PREFIX_TYPE` / `export class ClassNameUtils` / `export default`),故与 §4.1 同理 alias 到 `src`。用 `resolveClassnamesUtilsSrc()` 遍历 `.pnpm` 取第一个含 `src/index.ts` 的实例。
300
+
301
+ 对应 `vite.config.mts`:
302
+
303
+ ```ts
304
+ alias: {
305
+ // 顺序:`lib` 前缀要在裸包名之前
306
+ "c-formily-antd/lib": cFormilyAntdEsmDir, // c-formily-antd/lib/* -> esm/*
307
+ "c-formily-antd": path.join(cFormilyAntdEsmDir, "index.js"), // c-formily-antd -> esm/index.js
308
+ "@hzab/classnames-utils": classnamesUtilsSrc, // @hzab/classnames-utils -> src/index.ts
309
+ "turf-jsts": resolveTurfJstsEsm(), // -> jsts.mjs
310
+ }
311
+ ```
312
+
313
+ > 查找"带 `esm/` 的实例"用 `resolveCFormilyAntdEsm()`:遍历 `node_modules/.pnpm` 下 `c-formily-antd@*`,取第一个带 `esm/` 目录的实例。
314
+
315
+ ### 4.4 UMD 顶层 `this` 裸供 → `Cannot set properties of undefined (setting 'quickselect')`
316
+
317
+ - **现象**:`Cannot set properties of undefined (setting 'quickselect')`。
318
+ - **根因**:`quickselect` 是 `rbush` / `geojson-rbush` / `ol` / `@cesium/engine` 等的**传递依赖**,pnpm 不提升;其 1.x/2.x 是 UMD 包裹器 `(function (global, factory) { ... }(this, ...))`,顶层 `this` 被 Vite 当 ESM 服务时为 `undefined`。
319
+ - **修复**(排障手册 §4.1.1):alias 到一个带 `"type": "module"` 的原生 ESM 实例(3.0.0)。仅认 `type: "module"` —— 仅含 `module`/`index.js` 而缺 `type` 的实例(如 2.x)会被 Vite 按 CJS 误解析 `export default`。
320
+
321
+ ```ts
322
+ function resolveQuickselectEsm() {
323
+ // 遍历 .pnpm 下 quickselect@*,取首个 package.json 中 type === "module" 的实例
324
+ // entryFile = pkg.module || pkg.main || "index.js"
325
+ }
326
+ alias: { "quickselect": quickselectEsm }
327
+ ```
328
+
329
+ ### 4.5 构建期 CSS 老 IE hack → lightningcss 报错
330
+
331
+ - **现象**:`[lightningcss minify] Unexpected token Semicolon` / `star property hack`。
332
+ - **修复**:`vite.css.lightningcss = { errorRecovery: true }`,剥离早已失效的 `*zoom` / `*display` / `*width` 等 IE hack,降级为 warning(排障手册 §4.3)。
333
+
334
+ ### 4.6 React Compiler 缺包 → 构建失败
335
+
336
+ - **现象**:`Cannot find package 'babel-plugin-react-compiler'`。
337
+ - **根因**:`@hzab/vite-config` 默认 `reactCompiler: "build-only"`,build 时加载 preset,但包未安装。
338
+ - **修复**:`reactCompiler: false`(本项目未启用;如需启用先 `pnpm add -D babel-plugin-react-compiler` 再改回 `"build-only"`)(排障手册 §4.4)。
339
+
340
+ ### 4.7 dev 阶段逐个报错,build 一次性暴露
341
+
342
+ 用 `vite build` 走完整依赖图并链接,可一次列出**所有** `is not exported` / `does not provide an export named`,适合批量巡检(排障手册 §3):
343
+
344
+ ```bash
345
+ npm run build-flow_dev
346
+ ```
347
+
348
+ ### 4.8 浏览器端 `process` 未定义 → `ReferenceError: process is not defined`
349
+
350
+ - **现象**:`ReferenceError: process is not defined`,多出现在自己的 axios 封装或依赖源码包里。本项目落在 `src/utils/axios.js:18`(`process.env.BUSINESS_PLATFORM`)。
351
+ - **根因**:webpack 会 polyfill 全局 `process`(并用 DefinePlugin 注入 `process.env.*`);Vite 默认**只**替换 `process.env.NODE_ENV`,其余 `process.env.*`(`BUSINESS_PLATFORM` / `PACKAGE_VERSION` / `WEBPACK_PUBLIC_PATH` / `WEBPACK_ENV` / `APP_VERSION`)在浏览器端原样残留。
352
+ - **修复**(两步,缺一不可):
353
+ 1. **`vite.define` 注入**(对齐 webpack DefinePlugin 的 `processEnv`):把 `WEBPACK_ENV` / `WEBPACK_PUBLIC_PATH` / `PACKAGE_VERSION` 与用户自定义 `BUSINESS_PLATFORM`,以及源码用到的 `APP_VERSION`,全部用 `JSON.stringify(...)` 定义到 `vite.define`。覆盖**应用源码**与 **build**(`dist` 产物无裸 `process.env.*`)。
354
+ 2. **`index.html` 全局 `process` polyfill**:因为 **Vite 的依赖预构建(`optimizeDeps`)不经过 `define`**,被预构建的源码包(如 `@hzab/data-model`)内部的 `process.env.*`(如 `WEBPACK_PUBLIC_PATH`)在 dev 仍会以裸 `process` 残留。在 `index.html` 顶部注入 `window.process = window.process || { env: {} };` 兜底所有预构建 / 第三方裸 `process` 引用。
355
+
356
+ 对应 `vite.config.mts` 与 `index.html` 改动:
357
+
358
+ ```ts
359
+ // vite.config.mts(摘录)
360
+ const pkgJson = JSON.parse(fs.readFileSync(path.resolve(rootDir, "package.json"), "utf8"));
361
+ const PACKAGE_VERSION = pkgJson.version || "";
362
+ // ...
363
+ vite: {
364
+ define: {
365
+ "process.env.BUSINESS_PLATFORM": JSON.stringify(process.env.BUSINESS_PLATFORM || "unknown"),
366
+ "process.env.WEBPACK_ENV": JSON.stringify(mode),
367
+ "process.env.WEBPACK_PUBLIC_PATH": JSON.stringify(""),
368
+ "process.env.PACKAGE_VERSION": JSON.stringify(PACKAGE_VERSION),
369
+ "process.env.APP_VERSION": JSON.stringify(PACKAGE_VERSION),
370
+ },
371
+ }
372
+ ```
373
+
374
+ ```html
375
+ <!-- index.html(head 顶部) -->
376
+ <script>
377
+ window.process = window.process || { env: {} };
378
+ </script>
379
+ ```
380
+
381
+ > 备注:`APP_VERSION` 在 webpack 侧本就未注入(原为 `undefined`),迁移时补为 `PACKAGE_VERSION` 使水印呈现版本号。
382
+
383
+ ### 4.9 `import.meta.glob` 动态路由 + 让全部页面可编译(`vite build` 全绿)
384
+
385
+ > 本节为让 `vite build` 通过所需的**一段完整迁移链路**。核心报错(`Failed to resolve module specifier`)由动态路由修复解决;而 `import.meta.glob` 把此前被 `@vite-ignore` 排除的页面全部纳入构建后,会一次性暴露页面自身的语法/导出差异,需逐类处理。
386
+
387
+ **动态路由 `Failed to resolve module specifier`**:`anbao-router/index.tsx` 原先 `import(/* @vite-ignore */"@" + routeObj.component)`;`@vite-ignore` 使 Vite 跳过分析,`@/` 前缀在运行时成为浏览器无法解析的裸说明符。改为 `import.meta.glob("/src/**/*.{jsx,tsx}")` 预注册全部路由组件 + `resolveComponent`(按 `component` 补扩展名 / index 兜底),仍按需懒加载。
388
+
389
+ **`.js` 里写 JSX(`Unexpected JSX expression`)**:项目与 `@hzab/*` 源码包大量存在「扩展名 `.js` 却含 JSX」的文件。webpack 靠 babel-loader 转译;Vite 8 (rolldown) 的 transform 由 **oxc** 接管——`OxcOptions` 已 `Omit lang`(按扩展名推断),`esbuild` 配置被忽略(提示 `esbuild options will be ignored`)。解决:
390
+
391
+ 1. `src/` 下含 JSX 的 `.js` 直接改名 `.jsx`(`list.js`→`list.jsx`、`columns.js`→`columns.jsx`、`listColums.js`→…)。
392
+ 2. `node_modules` 里不可改的文件(如 `@hzab/formula-editor` 的 `ScrollContainer.js`)用**自定义插件 `jsx-in-js`**:以 `enforce:"pre"` + `vite` 的 `transformWithOxc(code, id, { lang:"jsx", jsxRuntime:"automatic" })` 预转换,一段插件同时覆盖 src 与 node_modules。
393
+
394
+ `vite.config.mts` 中的定义(需 `import { transformWithOxc } from "vite"`,并加入 `plugins`):
395
+
396
+ ```ts
397
+ const jsxInJsPlugin = {
398
+ name: "jsx-in-js",
399
+ enforce: "pre" as const,
400
+ async transform(code: string, id: string) {
401
+ if (!id.endsWith(".js")) return;
402
+ if (id.includes("/node_modules/.vite/")) return; // 预构建产物不重复处理
403
+ try {
404
+ return await transformWithOxc(code, id, {
405
+ lang: "jsx",
406
+ sourceType: "module",
407
+ jsxRuntime: "automatic",
408
+ jsxImportSource: "react",
409
+ } as any);
410
+ } catch {
411
+ return; // 转换失败交回后续管线(可能是已无 JSX 的正常 .js)
412
+ }
413
+ },
414
+ };
415
+ ```
416
+
417
+ **`const` 重赋值(`ILLEGAL_REASSIGNMENT`)**:`const width = …` 后又 `width = 150`。Babel 降级 `var` 掩盖;Rolldown 保留 `const` 报错。改 `const`→`let`(如 `salary-management/import-work-hours/detail/index.jsx`)。
418
+
419
+ **`MISSING_EXPORT "default"`**(Vite 与原 webpack 的默认导出语义差异):
420
+
421
+ - `import style from "./x.less"`:Vite 的 `.less` 无 default export;改为副作用导入 `import "./x.less"`(如 `components/NoPermission/index.jsx`,`style` 本未使用)。
422
+ - `import pdfjsWorker from "pdfjs-dist/build/pdf.worker.entry"`:webpack 将其打包为 worker;Vite 用 `?url` 取 worker 地址:`import pdfjsWorker from "pdfjs-dist/build/pdf.worker.min.js?url"`(`training-center/utils.ts`)。
423
+
424
+ **pnpm 隔离下直接 import 未提升的包(`Failed to resolve import`)**:业务源码直接 import 了只作为传递依赖存在的包。逐项提升为直接依赖 + `pnpm install`:`@formily/react@2.3.1`、`cropperjs@1.6.3`、`dompurify@3.4.14`、`qs@6.15.3`。可用 `scripts` 临时脚本扫描 `src` 裸包导入并检测未提升项,避免逐轮 build 逐个暴露。
425
+
426
+ **webpack alias 遗留**:`hzab-schema-list-render` / `hzab-schema-form-render`(`config/webpack.config.js` 指向 `packages/pc/*`)在 Vite `alias` 补回。
427
+
428
+ ### 4.10 提交被 pre-commit 截断 → `'lint-staged' 不是内部或外部命令`
429
+
430
+ - **现象**:`git commit` 时 husky 的 pre-commit 钩子中断并报 `'lint-staged' 不是内部或外部命令,也不是可运行的程序或批处理文件`(Windows),钩子退出码 1,提交失败。
431
+ - **根因**:`.husky/pre-commit` 执行 `npx lint-staged`,但 `lint-staged` 没有列入 `package.json` 的 `devDependencies`,只是某个依赖的**传递依赖**。pnpm 的隔离布局不会把传递依赖的 bin 链接到根目录 `node_modules/.bin`,因此钩子里直接找不到该命令。
432
+ - **修复**:把 `lint-staged` 加进 `devDependencies` 并 `pnpm install`(本项目锁定 `13.2.3`,与锁文件一致),使之链接到顶层 `node_modules/.bin`。同时补充一个容易踩的小点——`.husky/pre-commit` 里 `npx lint-staged` 应只写一行,重复行会导致 lint-staged 连续执行两次。
433
+ - **说明**:`package.json` 顶层 `lint-staged` 字段会对暂存文件执行 `prettier --write`,因此 `prettier` 也必须在 `devDependencies`(本项目 `2.8.7`)。
434
+
435
+ ---
436
+
437
+ ## 5. 涉及改动文件清单
438
+
439
+ | 文件 | 改动 |
440
+ | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
441
+ | `vite.config.mts` | 新增,接入 `createAppViteConfig` + 各类 alias / 插件 / `vite` 覆盖 |
442
+ | `package.json` | 新增 Vite 相关 devDependencies、`@hzab/vite-config`;提升 `react-is` / `deep-equal` / `geojson-equality` 为直接依赖;新增 `lint-staged` devDependency 与顶层 `lint-staged` 配置字段;scripts 改为 `cross-env` + `vite` |
443
+ | `.husky/pre-commit` | 预检钩子,提交前执行 `npx lint-staged`(已去除重复行) |
444
+ | `index.html` | webpack 模板 → vite-plugin-html EJS 模板(`PUBLIC_PATH` / `process.env.*`) |
445
+ | `src/vite-env.d.ts` | 新增,`vite/client` + `@hzab/vite-config/svg-react` 类型引用 |
446
+ | `src/package/anbao-router/index.tsx` | webpack 语法 → Vite 标准 `import` / `lazy`(含 `@vite-ignore`) |
447
+ | `pnpm-lock.yaml` | 新增 / 更新(pnpm 安装结果) |
448
+ | `pnpm-workspace.yaml` | 新增 `allowBuilds` + `minimumReleaseAgeExclude` |
449
+ | `config/webpack.config.js` | 迁移前基线,保留作对照(若不再使用可移除) |
450
+
451
+ ---
452
+
453
+ ## 6. 复用自查清单
454
+
455
+ > 新项目复用本工程接入方案时,逐条核对:
456
+
457
+ 1. `pnpm install` 后,app 依赖的**共享 CJS 老包**(`react-is`、`deep-equal`、`geojson-equality`、`classnames`、`prop-types`、`dayjs` …)是否在顶层 `node_modules`?不在 → 提升为直接依赖 + 加入 `optimizeDeps.include`(§4.1 / §4.2)。
458
+ 2. 报 `require is not defined`(而非 `module is not defined`)→ 先定位**父入口包**(被 `viteCommonjs.include` 转换的 CJS 包),提升**入口包**并 include,同时从 `viteCommonjs.include` 移除(§4.2),别逐个加叶子包。
459
+ 3. 报 `does not provide an export named 'X'` → 查该包在 `.pnpm` 里是否有带 `esm/` 的实例;有 → §4.3 alias 方案。
460
+ 4. 报 `Cannot set properties of undefined (setting 'X')` → UMD 顶层 `this` 裸供;查 `.pnpm` 里是否有 `"type": "module"` 的实例 → alias(§4.4)。
461
+ 5. `optimizeDeps.include` 报 `Failed to resolve dependency` → 说明还没到顶层,先提升依赖 + `pnpm install`,再 include。
462
+ 6. 构建报 LightningCSS `star property hack` → §4.5 `errorRecovery`。
463
+ 7. 构建报 `babel-plugin-react-compiler` 缺失 → §4.6 `reactCompiler: false` 或补装。
464
+ 8. 用 `vite build` 做全量「导出缺失」巡检,一次暴露所有同款问题(§4.7)。
465
+ 9. `git commit` 被 pre-commit 截断(报 `lint-staged` 找不到)→ 确认 `lint-staged` / `prettier` 都在 `devDependencies` 且已 `pnpm install`。pnpm 不会链接未声明依赖的 bin(§4.10)。
466
+
467
+ ---
468
+
469
+ ## 7. 遗留事项 / 风险(待确认)
470
+
471
+ 以下为接入后对照现状发现的**未完成或潜在风险**,未在本轮进行处理,仅作记录:
472
+
473
+ 1. **`@svgr/*` peer 未安装**:`vite.config.mts` 已开启 `svgr: true`,但 `@svgr/core`、`@svgr/plugin-jsx`(及默认开启的 `@svgr/plugin-svgo`)不在依赖清单,`require.resolve('@svgr/core')` 报 `MODULE_NOT_FOUND`。若构建走到 `*.svg?react` 通道会缺依赖报错。需补装或关闭 `svgr`;同时注意开启后组件导入需由 `?svgEle` 改为 `?react`。
474
+ 2. **`beforeBuild()` 的 routes 复制未迁移**:webpack 侧构建前会清空并复制 `config/routes/${BUSINESS_PLATFORM}/` 到 `public/routes`;`vite.config.mts` 未配置 `onRun` 对应逻辑。若业务依赖 `public/routes` 产物,需在 `onRun` 中补回。
475
+ 3. **`hashDeploy` + `base` 组合**:所有 `*build*` 脚本现已统一 `--mode production` 以启用 hash(产物为 `dist/<commit>-YYYY-MM-DD-HH-mm-ss>/`),当前未显式传 `base`(默认 `"./"`,启用 hash 后实际为 `./<hash>/`)。若产物要部署在固定 CDN 前缀,需传 `base: "https://cdn.example.com/app/"`(config 里注释已预留),且注意 `hashDeploy` 时实际前缀为 `{base}{hash}/`;`hashCleanup: { keep: 3 }` 只保留最新 3 个旧版本,需按需调整。
476
+ 4. **`publicConfig` 键与 `dest`**:`publicConfig.mode` 现取 `process.env.PUBLIC_CONF_DIR || mode`(按 `PUBLIC_CONF_DIR` 选配置目录),`dest: "public/config"` 与 `index.html` 里 `PUBLIC_PATH + "public/config/config.js"` 保持一致;若改 dest 或改写 PUBLIC_CONF_DIR 规则,需同步改模板引用。