@hzab/vite-config 0.0.2-alpha.0 → 0.0.3-alpha.1

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 (88) hide show
  1. package/CHANGELOG.md +95 -83
  2. package/LICENSE +21 -21
  3. package/README.md +184 -173
  4. package/dist/create-app-vite-config.cjs +160 -27
  5. package/dist/create-app-vite-config.cjs.map +1 -1
  6. package/dist/create-app-vite-config.js +160 -27
  7. package/dist/create-app-vite-config.js.map +1 -1
  8. package/dist/create-library-vite-config.cjs +39 -4
  9. package/dist/create-library-vite-config.cjs.map +1 -1
  10. package/dist/create-library-vite-config.js +38 -3
  11. package/dist/create-library-vite-config.js.map +1 -1
  12. package/dist/create-package-vitest-config.cjs.map +1 -1
  13. package/dist/create-package-vitest-config.js.map +1 -1
  14. package/dist/create-vite-config.cjs +160 -27
  15. package/dist/create-vite-config.cjs.map +1 -1
  16. package/dist/create-vite-config.js +160 -27
  17. package/dist/create-vite-config.js.map +1 -1
  18. package/dist/index.cjs +198 -30
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +1 -1
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.js +199 -31
  23. package/dist/index.js.map +1 -1
  24. package/dist/plugins/copy.cjs.map +1 -1
  25. package/dist/plugins/copy.js.map +1 -1
  26. package/dist/plugins/hash-deploy.cjs +150 -25
  27. package/dist/plugins/hash-deploy.cjs.map +1 -1
  28. package/dist/plugins/hash-deploy.d.cts +16 -5
  29. package/dist/plugins/hash-deploy.d.ts +16 -5
  30. package/dist/plugins/hash-deploy.js +150 -25
  31. package/dist/plugins/hash-deploy.js.map +1 -1
  32. package/dist/plugins/less-tilde.cjs.map +1 -1
  33. package/dist/plugins/less-tilde.d.cts +17 -2
  34. package/dist/plugins/less-tilde.d.ts +17 -2
  35. package/dist/plugins/less-tilde.js.map +1 -1
  36. package/dist/plugins/lifecycle.cjs.map +1 -1
  37. package/dist/plugins/lifecycle.js.map +1 -1
  38. package/dist/plugins/public-assets.cjs.map +1 -1
  39. package/dist/plugins/public-assets.js.map +1 -1
  40. package/dist/plugins/public-config.cjs.map +1 -1
  41. package/dist/plugins/public-config.js.map +1 -1
  42. package/dist/plugins/react-compiler.cjs.map +1 -1
  43. package/dist/plugins/react-compiler.js.map +1 -1
  44. package/dist/plugins/relative-base.cjs.map +1 -1
  45. package/dist/plugins/relative-base.js.map +1 -1
  46. package/dist/plugins/stub-less.cjs.map +1 -1
  47. package/dist/plugins/stub-less.js.map +1 -1
  48. package/dist/plugins/svg-react.cjs.map +1 -1
  49. package/dist/plugins/svg-react.js.map +1 -1
  50. package/dist/types.d.cts +19 -8
  51. package/dist/types.d.ts +19 -8
  52. package/dist/vitest.cjs.map +1 -1
  53. package/dist/vitest.js.map +1 -1
  54. package/docs/README.md +15 -15
  55. package/docs/abt-management-ui/vite.config.mts +226 -226
  56. package/docs/api.md +404 -366
  57. package/docs/migration-from-webpack.md +723 -722
  58. package/docs/sync-public-path.md +52 -52
  59. package/docs/vite-config-integration.md +477 -476
  60. package/docs/vite-pnpm-integration.md +279 -279
  61. package/docs/vs-ccc-vite-config.md +26 -26
  62. package/docs/webpack-gap.md +108 -107
  63. package/package.json +1 -1
  64. package/src/client.d.ts +9 -9
  65. package/src/create-app-vite-config.ts +236 -218
  66. package/src/create-library-vite-config.ts +248 -199
  67. package/src/create-package-vitest-config.ts +54 -54
  68. package/src/create-vite-config.ts +22 -22
  69. package/src/index.ts +41 -42
  70. package/src/plugins/copy.ts +25 -25
  71. package/src/plugins/hash-deploy.ts +239 -199
  72. package/src/plugins/hash-dir-name.ts +212 -0
  73. package/src/plugins/less-tilde.ts +72 -44
  74. package/src/plugins/lifecycle.ts +40 -40
  75. package/src/plugins/public-assets.ts +28 -28
  76. package/src/plugins/public-config.ts +34 -34
  77. package/src/plugins/react-compiler.ts +32 -32
  78. package/src/plugins/relative-base.ts +20 -20
  79. package/src/plugins/stub-less.ts +26 -26
  80. package/src/plugins/svg-react.ts +90 -90
  81. package/src/svg-react-runtime.ts +4 -4
  82. package/src/svg-react.d.ts +6 -6
  83. package/src/types.ts +325 -314
  84. package/src/vitest-types.ts +20 -20
  85. package/src/vitest.ts +2 -2
  86. package/templates/src/vite-env.d.ts +2 -2
  87. package/templates/tsconfig.json +12 -12
  88. package/templates/vite.config.ts +26 -26
@@ -1,199 +1,248 @@
1
- import path from "node:path";
2
- import basicSsl from "@vitejs/plugin-basic-ssl";
3
- import react from "@vitejs/plugin-react";
4
- import { mergeConfig, type PluginOption, type UserConfig } from "vite";
5
- import { createHtmlPlugin } from "vite-plugin-html";
6
-
7
- import { lifecyclePlugin } from "./plugins/lifecycle.ts";
8
- import { buildLessOptions } from "./plugins/less-tilde.ts";
9
- import { reactCompilerPlugin } from "./plugins/react-compiler.ts";
10
- import { svgReactPlugin } from "./plugins/svg-react.ts";
11
-
12
- import type { CreateLibraryViteConfigOptions, LibraryFormats } from "./types.ts";
13
-
14
- /**
15
- * 组件库构建默认外置
16
- * 传入 `externals` 时整表替换;追加时展开本常量。
17
- * @public
18
- */
19
- export const DEFAULT_LIBRARY_EXTERNALS = ["react", "react-dom"] as const;
20
-
21
- /**
22
- * UMD / IIFE 默认全局名。未出现在表里的字符串 external 用自身包名。
23
- * @public
24
- */
25
- export const DEFAULT_LIBRARY_GLOBALS: Record<string, string> = {
26
- react: "React",
27
- "react-dom": "ReactDOM",
28
- };
29
-
30
- const DEFAULT_LIBRARY_FORMATS: LibraryFormats[] = ["umd"];
31
-
32
- function needsLibraryName(formats: readonly LibraryFormats[]): boolean {
33
- return formats.includes("umd") || formats.includes("iife");
34
- }
35
-
36
- function resolveExternals(
37
- externals: CreateLibraryViteConfigOptions["externals"],
38
- ): (string | RegExp)[] {
39
- if (externals === false) return [];
40
- if (externals == null) return [...DEFAULT_LIBRARY_EXTERNALS];
41
- return externals;
42
- }
43
-
44
- function resolveLibraryFileName(
45
- fileName: CreateLibraryViteConfigOptions["fileName"],
46
- formats: readonly LibraryFormats[],
47
- ): string | ((format: string, entryName: string) => string) {
48
- if (fileName != null) return fileName;
49
- if (formats.length === 1) {
50
- return () => "index.js";
51
- }
52
- return (format) => (format === "es" ? "index.js" : `index.${format}.js`);
53
- }
54
-
55
- function resolveLibraryGlobals(
56
- externals: readonly (string | RegExp)[],
57
- globals?: Record<string, string>,
58
- ): Record<string, string> {
59
- const inferred: Record<string, string> = {};
60
- for (const ext of externals) {
61
- if (typeof ext !== "string") continue;
62
- inferred[ext] = DEFAULT_LIBRARY_GLOBALS[ext] ?? ext;
63
- }
64
- return { ...inferred, ...globals };
65
- }
66
-
67
- /** 字符串 external 同时匹配子路径(如 `react` → `react/jsx-runtime`)。 */
68
- export function matchLibraryExternal(id: string, externals: readonly (string | RegExp)[]): boolean {
69
- const source = id.split("?")[0] ?? id;
70
- return externals.some((ext) => {
71
- if (typeof ext === "string") {
72
- return source === ext || source.startsWith(`${ext}/`);
73
- }
74
- return ext.test(source);
75
- });
76
- }
77
-
78
- function resolveLibraryGlobalName(id: string, globals: Record<string, string>): string {
79
- const source = id.split("?")[0] ?? id;
80
- if (globals[source]) return globals[source];
81
- const matched = Object.keys(globals).find(
82
- (key) => source === key || source.startsWith(`${key}/`),
83
- );
84
- return matched ? (globals[matched] ?? source) : source;
85
- }
86
-
87
- /**
88
- * 组装组件库 Vite 配置:build 走 `build.lib`(默认 UMD → `lib/`),serve 为预览应用。
89
- *
90
- * 不启用 Hash 部署、public 复制、public-config。不默认 `example/` 预览目录或 antd / Formily externals。
91
- *
92
- * 合并顺序:`base(options) → mergeConfig(base, vite) → configure(final)`
93
- * @public
94
- */
95
- export function createLibraryViteConfig(options: CreateLibraryViteConfigOptions): UserConfig {
96
- const {
97
- rootDir,
98
- command,
99
- alias,
100
- entry = "src/index.ts",
101
- name,
102
- outDir = "lib",
103
- fileName,
104
- cssFileName = "index",
105
- formats = DEFAULT_LIBRARY_FORMATS,
106
- externals: externalsOption,
107
- globals: globalsOption,
108
- useHttps = false,
109
- openBrowser = true,
110
- devProxy,
111
- reactCompiler = "build-only",
112
- react: enableReact = true,
113
- svgr: svgrOption = false,
114
- less,
115
- previewHtml,
116
- onRun,
117
- onDone,
118
- plugins: extraPlugins = [],
119
- vite: viteOverride,
120
- configure,
121
- } = options;
122
-
123
- const isDev = command === "serve";
124
- const isBuild = command === "build";
125
-
126
- if (isBuild && needsLibraryName(formats) && (name == null || name.trim() === "")) {
127
- throw new Error(
128
- '[vite-config] createLibraryViteConfig: `name` is required when formats include "umd" or "iife".',
129
- );
130
- }
131
-
132
- const plugins: PluginOption[] = [
133
- ...(svgrOption ? [svgReactPlugin(svgrOption === true ? {} : svgrOption)] : []),
134
- ...(enableReact ? [react()] : []),
135
- ...reactCompilerPlugin({ command, mode: reactCompiler }),
136
- ...(isDev && previewHtml
137
- ? [
138
- createHtmlPlugin({
139
- minify: false,
140
- template: path.resolve(rootDir, previewHtml),
141
- }),
142
- ]
143
- : []),
144
- ...(isDev && useHttps ? [basicSsl()] : []),
145
- ...extraPlugins,
146
- ...(isBuild && (onRun || onDone) ? [lifecyclePlugin({ onRun, onDone })] : []),
147
- ];
148
-
149
- const resolvedExternals = resolveExternals(externalsOption);
150
- const resolvedGlobals = resolveLibraryGlobals(resolvedExternals, globalsOption);
151
-
152
- const base: UserConfig = {
153
- root: rootDir,
154
- publicDir: false,
155
- plugins,
156
- resolve: {
157
- alias,
158
- },
159
- css: {
160
- preprocessorOptions: {
161
- less: buildLessOptions(less),
162
- },
163
- },
164
- ...(isDev
165
- ? {
166
- server: {
167
- https: useHttps ? {} : undefined,
168
- host: true,
169
- open: openBrowser,
170
- ...(devProxy ? { proxy: devProxy } : {}),
171
- },
172
- }
173
- : {
174
- build: {
175
- outDir,
176
- emptyOutDir: true,
177
- lib: {
178
- entry: path.resolve(rootDir, entry),
179
- ...(name != null && name.trim() !== "" ? { name } : {}),
180
- formats,
181
- fileName: resolveLibraryFileName(fileName, formats),
182
- cssFileName,
183
- },
184
- rolldownOptions: {
185
- external: (id: string) => matchLibraryExternal(id, resolvedExternals),
186
- output: {
187
- globals: (id: string) => resolveLibraryGlobalName(id, resolvedGlobals),
188
- },
189
- },
190
- },
191
- }),
192
- };
193
-
194
- let merged = viteOverride ? mergeConfig(base, viteOverride) : base;
195
- if (configure) {
196
- merged = configure(merged);
197
- }
198
- return merged;
199
- }
1
+ import { readFile, rm, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import basicSsl from "@vitejs/plugin-basic-ssl";
4
+ import react from "@vitejs/plugin-react";
5
+ import { mergeConfig, type Plugin, type PluginOption, type UserConfig } from "vite";
6
+ import { createHtmlPlugin } from "vite-plugin-html";
7
+
8
+ import { lifecyclePlugin } from "./plugins/lifecycle.ts";
9
+ import { buildLessOptions } from "./plugins/less-tilde.ts";
10
+ import { reactCompilerPlugin } from "./plugins/react-compiler.ts";
11
+ import { svgReactPlugin } from "./plugins/svg-react.ts";
12
+
13
+ import type { CreateLibraryViteConfigOptions, LibraryFormats } from "./types.ts";
14
+
15
+ /**
16
+ * 组件库构建默认外置
17
+ * 传入 `externals` 时整表替换;追加时展开本常量。
18
+ * @public
19
+ */
20
+ export const DEFAULT_LIBRARY_EXTERNALS = ["react", "react-dom"] as const;
21
+
22
+ /**
23
+ * UMD / IIFE 默认全局名。未出现在表里的字符串 external 用自身包名。
24
+ * @public
25
+ */
26
+ export const DEFAULT_LIBRARY_GLOBALS: Record<string, string> = {
27
+ react: "React",
28
+ "react-dom": "ReactDOM",
29
+ };
30
+
31
+ const DEFAULT_LIBRARY_FORMATS: LibraryFormats[] = ["umd"];
32
+
33
+ /**
34
+ * 删除 CJS 产物的 sourcemap,并抹掉产物末尾的 `sourceMappingURL` 注释。
35
+ *
36
+ * 理由:webpack 5(`exports.import`)与 webpack 4(`mainFields: browser → module → main`)都命中
37
+ * ESM 产物,CJS map 只对 Node SSR + `--enable-source-maps` 有意义,却让随包 map 体积翻倍
38
+ * (实测 `form-render` 双份 701KB、`form-render-mobile` 622KB,超 check-package 的 512KB 守卫)。
39
+ * 源码调试由 ESM map(含 `sourcesContent`)+ 随包发布的 `src` 覆盖。
40
+ * 决策见 docs/src-direct-vs-dist-evaluation.md §11 第 6 项 (c)。
41
+ */
42
+ function stripCjsSourcemapPlugin(): Plugin {
43
+ let outDir = "";
44
+ return {
45
+ name: "hzab:strip-cjs-sourcemap",
46
+ apply: "build",
47
+ configResolved(config) {
48
+ outDir = config.build.outDir;
49
+ },
50
+ async writeBundle(_options, bundle) {
51
+ for (const fileName of Object.keys(bundle)) {
52
+ const file = path.resolve(outDir, fileName);
53
+ if (fileName.endsWith(".cjs.map")) {
54
+ await rm(file, { force: true });
55
+ continue;
56
+ }
57
+ if (!fileName.endsWith(".cjs")) continue;
58
+ // 注释必须一起删:留着会让 DevTools / webpack 去请求已不存在的 map。
59
+ const code = await readFile(file, "utf8");
60
+ const stripped = code.replace(/\n?\/\/# sourceMappingURL=\S+\s*$/u, "\n");
61
+ if (stripped !== code) await writeFile(file, stripped, "utf8");
62
+ }
63
+ },
64
+ };
65
+ }
66
+
67
+ function needsLibraryName(formats: readonly LibraryFormats[]): boolean {
68
+ return formats.includes("umd") || formats.includes("iife");
69
+ }
70
+
71
+ function resolveExternals(
72
+ externals: CreateLibraryViteConfigOptions["externals"],
73
+ ): (string | RegExp)[] {
74
+ if (externals === false) return [];
75
+ if (externals == null) return [...DEFAULT_LIBRARY_EXTERNALS];
76
+ return externals;
77
+ }
78
+
79
+ function resolveLibraryFileName(
80
+ fileName: CreateLibraryViteConfigOptions["fileName"],
81
+ formats: readonly LibraryFormats[],
82
+ ): string | ((format: string, entryName: string) => string) {
83
+ if (fileName != null) return fileName;
84
+ if (formats.length === 1) {
85
+ return () => "index.js";
86
+ }
87
+ // cjs 产物用 `.cjs` 后缀:宿主包若声明 `"type": "module"`,`.js` 会被当作 ESM 解析,
88
+ // 而 cjs 产物内容是 CommonJS(module.exports),require() 会因 ESM 误判而失败。
89
+ return (format) => {
90
+ if (format === "es") return "index.js";
91
+ if (format === "cjs") return "index.cjs";
92
+ return `index.${format}.js`;
93
+ };
94
+ }
95
+
96
+ function resolveLibraryGlobals(
97
+ externals: readonly (string | RegExp)[],
98
+ globals?: Record<string, string>,
99
+ ): Record<string, string> {
100
+ const inferred: Record<string, string> = {};
101
+ for (const ext of externals) {
102
+ if (typeof ext !== "string") continue;
103
+ inferred[ext] = DEFAULT_LIBRARY_GLOBALS[ext] ?? ext;
104
+ }
105
+ return { ...inferred, ...globals };
106
+ }
107
+
108
+ /** 字符串 external 同时匹配子路径(如 `react` → `react/jsx-runtime`)。 */
109
+ export function matchLibraryExternal(id: string, externals: readonly (string | RegExp)[]): boolean {
110
+ const source = id.split("?")[0] ?? id;
111
+ return externals.some((ext) => {
112
+ if (typeof ext === "string") {
113
+ return source === ext || source.startsWith(`${ext}/`);
114
+ }
115
+ return ext.test(source);
116
+ });
117
+ }
118
+
119
+ function resolveLibraryGlobalName(id: string, globals: Record<string, string>): string {
120
+ const source = id.split("?")[0] ?? id;
121
+ if (globals[source]) return globals[source];
122
+ const matched = Object.keys(globals).find(
123
+ (key) => source === key || source.startsWith(`${key}/`),
124
+ );
125
+ return matched ? (globals[matched] ?? source) : source;
126
+ }
127
+
128
+ /**
129
+ * 组装组件库 Vite 配置:build 走 `build.lib`(默认 UMD → `lib/`),serve 为预览应用。
130
+ *
131
+ * 不启用 Hash 部署、public 复制、public-config。不默认 `example/` 预览目录或 antd / Formily externals。
132
+ *
133
+ * 合并顺序:`base(options) → mergeConfig(base, vite) → configure(final)`
134
+ * @public
135
+ */
136
+ export function createLibraryViteConfig(options: CreateLibraryViteConfigOptions): UserConfig {
137
+ const {
138
+ rootDir,
139
+ command,
140
+ alias,
141
+ entry = "src/index.ts",
142
+ name,
143
+ outDir = "lib",
144
+ fileName,
145
+ cssFileName = "index",
146
+ formats = DEFAULT_LIBRARY_FORMATS,
147
+ externals: externalsOption,
148
+ globals: globalsOption,
149
+ useHttps = false,
150
+ openBrowser = true,
151
+ devProxy,
152
+ reactCompiler = "build-only",
153
+ react: enableReact = true,
154
+ svgr: svgrOption = false,
155
+ less,
156
+ previewHtml,
157
+ onRun,
158
+ onDone,
159
+ plugins: extraPlugins = [],
160
+ vite: viteOverride,
161
+ configure,
162
+ } = options;
163
+
164
+ const isDev = command === "serve";
165
+ const isBuild = command === "build";
166
+
167
+ if (isBuild && needsLibraryName(formats) && (name == null || name.trim() === "")) {
168
+ throw new Error(
169
+ '[vite-config] createLibraryViteConfig: `name` is required when formats include "umd" or "iife".',
170
+ );
171
+ }
172
+
173
+ const plugins: PluginOption[] = [
174
+ ...(svgrOption ? [svgReactPlugin(svgrOption === true ? {} : svgrOption)] : []),
175
+ ...(enableReact ? [react()] : []),
176
+ ...reactCompilerPlugin({ command, mode: reactCompiler }),
177
+ ...(isDev && previewHtml
178
+ ? [
179
+ createHtmlPlugin({
180
+ minify: false,
181
+ template: path.resolve(rootDir, previewHtml),
182
+ }),
183
+ ]
184
+ : []),
185
+ ...(isDev && useHttps ? [basicSsl()] : []),
186
+ ...extraPlugins,
187
+ ...(isBuild && (onRun || onDone) ? [lifecyclePlugin({ onRun, onDone })] : []),
188
+ ...(isBuild ? [stripCjsSourcemapPlugin()] : []),
189
+ ];
190
+
191
+ const resolvedExternals = resolveExternals(externalsOption);
192
+ const resolvedGlobals = resolveLibraryGlobals(resolvedExternals, globalsOption);
193
+
194
+ const base: UserConfig = {
195
+ root: rootDir,
196
+ publicDir: false,
197
+ plugins,
198
+ resolve: {
199
+ alias,
200
+ },
201
+ css: {
202
+ preprocessorOptions: {
203
+ less: buildLessOptions(less),
204
+ },
205
+ },
206
+ ...(isDev
207
+ ? {
208
+ server: {
209
+ https: useHttps ? {} : undefined,
210
+ host: true,
211
+ open: openBrowser,
212
+ ...(devProxy ? { proxy: devProxy } : {}),
213
+ },
214
+ }
215
+ : {
216
+ build: {
217
+ outDir,
218
+ emptyOutDir: true,
219
+ // 产物随包发布:消费方 webpack 的 devtool 会消费依赖自带的 map,缺失时
220
+ // DevTools 只能看到缩短标识符后的编译产物(见 docs/src-direct-vs-dist-evaluation.md §7.1)。
221
+ sourcemap: true,
222
+ // 降到 ES2018:webpack 4(umi3 线 abt-app)内置 acorn 6 解析到 ES2019 为止,不认 ES2020 的
223
+ // `?.` / `??`,产物保持默认 target 会让该线直接 Module parse failed。ES2018 是覆盖 acorn 6
224
+ // 边界的最小目标(对象展开仍保留),见 docs/src-direct-vs-dist-evaluation.md §7.2。
225
+ target: "es2018",
226
+ lib: {
227
+ entry: path.resolve(rootDir, entry),
228
+ ...(name != null && name.trim() !== "" ? { name } : {}),
229
+ formats,
230
+ fileName: resolveLibraryFileName(fileName, formats),
231
+ cssFileName,
232
+ },
233
+ rolldownOptions: {
234
+ external: (id: string) => matchLibraryExternal(id, resolvedExternals),
235
+ output: {
236
+ globals: (id: string) => resolveLibraryGlobalName(id, resolvedGlobals),
237
+ },
238
+ },
239
+ },
240
+ }),
241
+ };
242
+
243
+ let merged = viteOverride ? mergeConfig(base, viteOverride) : base;
244
+ if (configure) {
245
+ merged = configure(merged);
246
+ }
247
+ return merged;
248
+ }
@@ -1,54 +1,54 @@
1
- import react from "@vitejs/plugin-react";
2
- import { mergeConfig, type PluginOption } from "vite";
3
-
4
- import { stubLessPlugin } from "./plugins/stub-less.ts";
5
-
6
- import type { CreatePackageVitestConfigOptions } from "./vitest-types.ts";
7
- import type { ViteUserConfig as VitestUserConfig } from "vitest/config";
8
-
9
- /**
10
- * 组装包级 Vitest 配置。
11
- *
12
- * 合并顺序:`base(options) → mergeConfig(base, vite) → configure(final)`
13
- */
14
- export function createPackageVitestConfig(
15
- options: CreatePackageVitestConfigOptions,
16
- ): VitestUserConfig {
17
- const {
18
- packageRoot,
19
- alias,
20
- react: enableReact = false,
21
- stubLess = false,
22
- environment = "happy-dom",
23
- include = ["test/**/*.test.ts"],
24
- setupFiles,
25
- plugins: extraPlugins = [],
26
- vite: viteOverride,
27
- configure,
28
- } = options;
29
-
30
- const plugins: PluginOption[] = [
31
- ...(enableReact ? [react()] : []),
32
- ...(stubLess ? [stubLessPlugin()] : []),
33
- ...extraPlugins,
34
- ];
35
-
36
- const base: VitestUserConfig = {
37
- root: packageRoot,
38
- plugins,
39
- resolve: {
40
- alias,
41
- },
42
- test: {
43
- environment,
44
- include,
45
- ...(setupFiles ? { setupFiles } : {}),
46
- },
47
- };
48
-
49
- let merged = viteOverride ? mergeConfig(base, viteOverride) : base;
50
- if (configure) {
51
- merged = configure(merged);
52
- }
53
- return merged;
54
- }
1
+ import react from "@vitejs/plugin-react";
2
+ import { mergeConfig, type PluginOption } from "vite";
3
+
4
+ import { stubLessPlugin } from "./plugins/stub-less.ts";
5
+
6
+ import type { CreatePackageVitestConfigOptions } from "./vitest-types.ts";
7
+ import type { ViteUserConfig as VitestUserConfig } from "vitest/config";
8
+
9
+ /**
10
+ * 组装包级 Vitest 配置。
11
+ *
12
+ * 合并顺序:`base(options) → mergeConfig(base, vite) → configure(final)`
13
+ */
14
+ export function createPackageVitestConfig(
15
+ options: CreatePackageVitestConfigOptions,
16
+ ): VitestUserConfig {
17
+ const {
18
+ packageRoot,
19
+ alias,
20
+ react: enableReact = false,
21
+ stubLess = false,
22
+ environment = "happy-dom",
23
+ include = ["test/**/*.test.ts"],
24
+ setupFiles,
25
+ plugins: extraPlugins = [],
26
+ vite: viteOverride,
27
+ configure,
28
+ } = options;
29
+
30
+ const plugins: PluginOption[] = [
31
+ ...(enableReact ? [react()] : []),
32
+ ...(stubLess ? [stubLessPlugin()] : []),
33
+ ...extraPlugins,
34
+ ];
35
+
36
+ const base: VitestUserConfig = {
37
+ root: packageRoot,
38
+ plugins,
39
+ resolve: {
40
+ alias,
41
+ },
42
+ test: {
43
+ environment,
44
+ include,
45
+ ...(setupFiles ? { setupFiles } : {}),
46
+ },
47
+ };
48
+
49
+ let merged = viteOverride ? mergeConfig(base, viteOverride) : base;
50
+ if (configure) {
51
+ merged = configure(merged);
52
+ }
53
+ return merged;
54
+ }
@@ -1,22 +1,22 @@
1
- import { createAppViteConfig } from "./create-app-vite-config.ts";
2
-
3
- import type { CreateAppViteConfigOptions, CreateAppViteConfigResult } from "./types.ts";
4
-
5
- /** @public */
6
- export type CreateViteConfigOptions = Partial<CreateAppViteConfigOptions>;
7
-
8
- /**
9
- * Default Vite factory for consumer apps.
10
- * Existing `createAppViteConfig` remains the full-control API.
11
- * @public
12
- */
13
- export function createViteConfig(options: CreateViteConfigOptions = {}): CreateAppViteConfigResult {
14
- return createAppViteConfig({
15
- rootDir: options.rootDir ?? process.cwd(),
16
- command: options.command ?? "serve",
17
- mode: options.mode ?? "development",
18
- openBrowser: options.openBrowser ?? false,
19
- reactCompiler: false,
20
- ...options,
21
- });
22
- }
1
+ import { createAppViteConfig } from "./create-app-vite-config.ts";
2
+
3
+ import type { CreateAppViteConfigOptions, CreateAppViteConfigResult } from "./types.ts";
4
+
5
+ /** @public */
6
+ export type CreateViteConfigOptions = Partial<CreateAppViteConfigOptions>;
7
+
8
+ /**
9
+ * Default Vite factory for consumer apps.
10
+ * Existing `createAppViteConfig` remains the full-control API.
11
+ * @public
12
+ */
13
+ export function createViteConfig(options: CreateViteConfigOptions = {}): CreateAppViteConfigResult {
14
+ return createAppViteConfig({
15
+ rootDir: options.rootDir ?? process.cwd(),
16
+ command: options.command ?? "serve",
17
+ mode: options.mode ?? "development",
18
+ openBrowser: options.openBrowser ?? false,
19
+ reactCompiler: false,
20
+ ...options,
21
+ });
22
+ }