@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,218 @@
1
+ import basicSsl from "@vitejs/plugin-basic-ssl";
2
+ import react from "@vitejs/plugin-react";
3
+ import { mergeConfig, type PluginOption, type UserConfig } from "vite";
4
+ import { createHtmlPlugin } from "vite-plugin-html";
5
+
6
+ import { copyPlugin } from "./plugins/copy.ts";
7
+ import { createHashBuildDirName, hashDeployPlugin } from "./plugins/hash-deploy.ts";
8
+ import { buildLessOptions } from "./plugins/less-tilde.ts";
9
+ import { lifecyclePlugin } from "./plugins/lifecycle.ts";
10
+ import { publicAssetsPlugin } from "./plugins/public-assets.ts";
11
+ import { publicConfigPlugin } from "./plugins/public-config.ts";
12
+ import { reactCompilerPlugin } from "./plugins/react-compiler.ts";
13
+ import { svgReactPlugin } from "./plugins/svg-react.ts";
14
+
15
+ import type { CreateAppViteConfigOptions, CreateAppViteConfigResult } from "./types.ts";
16
+
17
+ /** 根入口运行时资源前缀,供 JS `fetch` / 动态 URL 使用。与 HTML 子目录 `PUBLIC_PATH` 可能不同。 */
18
+ const JS_PUBLIC_PATH_DEFINE_KEY = "import.meta.env.PUBLIC_PATH";
19
+
20
+ /** 规范化资源 base:空串视为未设置;非空则保证尾 `/`。 */
21
+ function normalizeAssetBase(base: string | undefined): string | undefined {
22
+ if (base == null) return undefined;
23
+ const trimmed = base.trim();
24
+ if (!trimmed) return undefined;
25
+ return trimmed.endsWith("/") ? trimmed : `${trimmed}/`;
26
+ }
27
+
28
+ function ensureTrailingSlash(value: string): string {
29
+ return value.endsWith("/") ? value : `${value}/`;
30
+ }
31
+
32
+ /**
33
+ * JS 可读的根入口前缀。相对 hash 必须用 `./{hash}/`,不能用 Vite `base`(后者保持 `./`)。
34
+ * 非 hash 则跟最终 `config.base`;serve 未设 base 时为 `"/"`。
35
+ */
36
+ function resolveJsPublicPath(isHash: boolean, publicPath: string, config: UserConfig): string {
37
+ if (isHash) return publicPath;
38
+ if (typeof config.base === "string" && config.base.length > 0) {
39
+ return ensureTrailingSlash(config.base);
40
+ }
41
+ return publicPath || "/";
42
+ }
43
+
44
+ function applyJsPublicPathDefine(config: UserConfig, publicPath: string): UserConfig {
45
+ config.define = {
46
+ ...config.define,
47
+ [JS_PUBLIC_PATH_DEFINE_KEY]: JSON.stringify(publicPath),
48
+ };
49
+ return config;
50
+ }
51
+
52
+ /**
53
+ * 组装应用侧 Vite 配置。
54
+ *
55
+ * 合并顺序:`base(options) → mergeConfig(base, vite) → configure(final)`,
56
+ * 之后写入 `import.meta.env.PUBLIC_PATH`(同名 `define` 会被覆盖)。
57
+ *
58
+ * 返回值附带只读 `buildDirHash`(本次 hash 子目录名;未启用时为 `""`)。
59
+ * @public
60
+ */
61
+ export function createAppViteConfig(
62
+ options: CreateAppViteConfigOptions,
63
+ ): CreateAppViteConfigResult {
64
+ const {
65
+ rootDir,
66
+ repositoryRoot,
67
+ command,
68
+ mode,
69
+ alias,
70
+ useHttps = false,
71
+ openBrowser = true,
72
+ hashDeploy = false,
73
+ hashTimestamp = "epoch",
74
+ base: baseOption,
75
+ deployRoot: deployRootOption = "dist",
76
+ hashCleanup,
77
+ publicAssets,
78
+ publicConfig,
79
+ copy: copyOption,
80
+ htmlData,
81
+ devProxy,
82
+ reactCompiler = "build-only",
83
+ react: enableReact = true,
84
+ svgr: svgrOption = false,
85
+ less,
86
+ onRun,
87
+ onDone,
88
+ plugins: extraPlugins = [],
89
+ vite: viteOverride,
90
+ configure,
91
+ } = options;
92
+
93
+ const isDev = command === "serve";
94
+ const isBuild = command === "build";
95
+ const isHash = isBuild && Boolean(hashDeploy) && mode !== "development";
96
+ const deployRoot = deployRootOption.replace(/\/+$/, "") || "dist";
97
+ const assetBase = normalizeAssetBase(baseOption);
98
+
99
+ const buildDirStr = isHash
100
+ ? createHashBuildDirName({
101
+ repositoryRoot: repositoryRoot ?? rootDir,
102
+ timestampFormat: hashTimestamp,
103
+ })
104
+ : "";
105
+ /**
106
+ * HTML / 根入口资源前缀(JS `import.meta.env.PUBLIC_PATH` 用这个)。
107
+ * - hash + 相对:`./{hash}/`(Vite `base` 仍为 `./`,由插件改写根入口)
108
+ * - hash + 绝对 base:`{base}{hash}/`(与 Vite `base` 一致)
109
+ * - 普通 build:`base` 或 `./`
110
+ */
111
+ const publicPath = isHash
112
+ ? `${assetBase ?? "./"}${buildDirStr}/`
113
+ : isBuild
114
+ ? (assetBase ?? "./")
115
+ : "";
116
+ /**
117
+ * Hash 子目录入口相对于自身加载资源;根入口由 hashDeployPlugin 再补 hash 前缀。
118
+ * 绝对 base 则两个入口都使用同一个完整 URL。
119
+ */
120
+ const htmlPublicPath = isHash && publicPath.startsWith("./") ? "./" : publicPath;
121
+ /** 相对 base(含默认 `./`)在 hash 下必须保持 Vite `base: "./"`,否则 `./{hash}/` 会被规范成 `/`。 */
122
+ const isAbsoluteAssetBase =
123
+ assetBase != null &&
124
+ (assetBase.startsWith("https://") ||
125
+ assetBase.startsWith("http://") ||
126
+ assetBase.startsWith("/"));
127
+ const viteBase = isHash
128
+ ? isAbsoluteAssetBase
129
+ ? publicPath
130
+ : "./"
131
+ : isBuild
132
+ ? publicPath
133
+ : undefined;
134
+ const enablePublicAssets = publicAssets !== false;
135
+
136
+ const plugins: PluginOption[] = [
137
+ ...(enablePublicAssets
138
+ ? [publicAssetsPlugin(publicAssets && typeof publicAssets === "object" ? publicAssets : {})]
139
+ : []),
140
+ ...(svgrOption ? [svgReactPlugin(svgrOption === true ? {} : svgrOption)] : []),
141
+ ...(enableReact ? [react()] : []),
142
+ ...reactCompilerPlugin({ command, mode: reactCompiler }),
143
+ ...(publicConfig === false || publicConfig == null
144
+ ? []
145
+ : [
146
+ publicConfigPlugin({
147
+ sourceGlob: publicConfig.sourceGlob ?? `config/public-config/${publicConfig.mode}/*`,
148
+ dest: publicConfig.dest,
149
+ }),
150
+ ]),
151
+ ...(copyOption ? [copyPlugin(copyOption)] : []),
152
+ createHtmlPlugin({
153
+ minify: isBuild,
154
+ inject: {
155
+ data: {
156
+ ...htmlData,
157
+ PUBLIC_PATH: htmlPublicPath || "",
158
+ },
159
+ },
160
+ }),
161
+ ...(isBuild && isHash
162
+ ? [
163
+ hashDeployPlugin({
164
+ rootDir,
165
+ buildDirStr,
166
+ publicPath,
167
+ cleanup: hashCleanup,
168
+ }),
169
+ ]
170
+ : []),
171
+ ...(isDev && useHttps ? [basicSsl()] : []),
172
+ ...extraPlugins,
173
+ ...(isBuild && (onRun || onDone) ? [lifecyclePlugin({ onRun, onDone })] : []),
174
+ ];
175
+
176
+ const base: UserConfig = {
177
+ root: rootDir,
178
+ ...(viteBase != null ? { base: viteBase } : {}),
179
+ plugins,
180
+ ...(enablePublicAssets ? { publicDir: false } : {}),
181
+ resolve: {
182
+ alias,
183
+ },
184
+ css: {
185
+ preprocessorOptions: {
186
+ less: buildLessOptions(less),
187
+ },
188
+ },
189
+ ...(isDev
190
+ ? {
191
+ server: {
192
+ https: useHttps ? {} : undefined,
193
+ host: true,
194
+ open: openBrowser,
195
+ ...(devProxy ? { proxy: devProxy } : {}),
196
+ },
197
+ }
198
+ : {
199
+ build: {
200
+ outDir: isHash ? `${deployRoot}/${buildDirStr}/` : deployRoot,
201
+ assetsDir: "assets",
202
+ emptyOutDir: true,
203
+ },
204
+ }),
205
+ };
206
+
207
+ let merged = viteOverride ? mergeConfig(base, viteOverride) : base;
208
+ if (configure) {
209
+ merged = configure(merged);
210
+ }
211
+ applyJsPublicPathDefine(merged, resolveJsPublicPath(isHash, publicPath, merged));
212
+ Object.defineProperty(merged, "buildDirHash", {
213
+ value: buildDirStr,
214
+ enumerable: false,
215
+ configurable: true,
216
+ });
217
+ return merged as CreateAppViteConfigResult;
218
+ }
@@ -0,0 +1,199 @@
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
+ }
@@ -0,0 +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
+ }
@@ -0,0 +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
+ }
package/src/index.ts ADDED
@@ -0,0 +1,42 @@
1
+ export { createAppViteConfig } from "./create-app-vite-config.ts";
2
+ export { createViteConfig } from "./create-vite-config.ts";
3
+ export type { CreateViteConfigOptions } from "./create-vite-config.ts";
4
+ export {
5
+ createLibraryViteConfig,
6
+ DEFAULT_LIBRARY_EXTERNALS,
7
+ DEFAULT_LIBRARY_GLOBALS,
8
+ } from "./create-library-vite-config.ts";
9
+ export { copyPlugin } from "./plugins/copy.ts";
10
+ export type {
11
+ HashBuildDirNameOptions,
12
+ HashCleanupOptions,
13
+ HashDeployPluginOptions,
14
+ HashTimestampFormat,
15
+ } from "./plugins/hash-deploy.ts";
16
+ export { createHashBuildDirName, getCommitHash, hashDeployPlugin } from "./plugins/hash-deploy.ts";
17
+ export type { LifecyclePluginOptions } from "./plugins/lifecycle.ts";
18
+ export { lifecyclePlugin } from "./plugins/lifecycle.ts";
19
+ export { buildLessOptions, lessTildeResolutionPlugin } from "./plugins/less-tilde.ts";
20
+ export type { PublicAssetsPluginOptions } from "./plugins/public-assets.ts";
21
+ export { publicAssetsPlugin } from "./plugins/public-assets.ts";
22
+ export type { PublicConfigPluginOptions } from "./plugins/public-config.ts";
23
+ export { publicConfigPlugin } from "./plugins/public-config.ts";
24
+ export type { ReactCompilerPluginOptions } from "./plugins/react-compiler.ts";
25
+ export { reactCompilerPlugin } from "./plugins/react-compiler.ts";
26
+ export { relativeBasePlugin } from "./plugins/relative-base.ts";
27
+ export { stubLessPlugin } from "./plugins/stub-less.ts";
28
+ export { svgReactPlugin } from "./plugins/svg-react.ts";
29
+ export type {
30
+ CopyOption,
31
+ CopyPluginOptions,
32
+ CopyTarget,
33
+ CreateAppViteConfigOptions,
34
+ CreateAppViteConfigResult,
35
+ CreateLibraryViteConfigOptions,
36
+ LessOptions,
37
+ LibraryFormats,
38
+ PublicAssetsOptions,
39
+ PublicConfigOptions,
40
+ ReactCompilerMode,
41
+ SvgReactOptions,
42
+ } from "./types.ts";
@@ -0,0 +1,25 @@
1
+ import { viteStaticCopy } from "vite-plugin-static-copy";
2
+
3
+ import type { PluginOption } from "vite";
4
+ import type { Target, ViteStaticCopyOptions } from "vite-plugin-static-copy";
5
+
6
+ /** @public */
7
+ export type CopyTarget = Target;
8
+ /** @public */
9
+ export type CopyPluginOptions = ViteStaticCopyOptions;
10
+
11
+ /** @public */
12
+ export type CopyOption = CopyPluginOptions | CopyTarget[];
13
+
14
+ export function resolveCopyPluginOptions(options: CopyOption): CopyPluginOptions {
15
+ return Array.isArray(options) ? { targets: options } : options;
16
+ }
17
+
18
+ /**
19
+ * 通用静态复制,封装 `vite-plugin-static-copy`。
20
+ * 可传完整选项,或直接传 `targets` 数组。
21
+ * @public
22
+ */
23
+ export function copyPlugin(options: CopyOption): PluginOption {
24
+ return viteStaticCopy(resolveCopyPluginOptions(options));
25
+ }