@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
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Hash 子目录名模式串 → 实际目录名,以及清理历史目录用的匹配器。
3
+ *
4
+ * 与 `@hzab/webpack-config` 的 `hashDirName` 共用同一套 token 语义(两个包各自实现,不互相依赖):
5
+ * token 展开为值,其余字符(含 `-`)原样保留。
6
+ * - `hash` 12 位 commit(非 git 仓库回退 `local`)
7
+ * - `timestamp` 毫秒时间戳(`Date.now()`)
8
+ * - `YYYY` / `MM` / `DD` / `HH` / `mm` / `ss` / `SSS` 本地时区格式化时间
9
+ *
10
+ * 例(now = 2026-09-17 15:30:52.123,commit = a1b2c3d4e5f6):
11
+ * - `hash-timestamp` -> `a1b2c3d4e5f6-1789630252123`
12
+ * - `hash-timestamp-YYYYMMDDHHmmssSSS` -> `a1b2c3d4e5f6-1789630252123-20260917153052123`
13
+ * - `hash-YYYYMMDDHHmmssSSS` -> `a1b2c3d4e5f6-20260917153052123`
14
+ *
15
+ * 约束:模式串必须至少含一个时间 token(`timestamp` 或日期 token)。只含 `hash` 的目录名会让
16
+ * 同一 commit 的多次构建互相覆盖,因此被拒绝。
17
+ *
18
+ * 只做纯字符串计算(无 I/O),命名与清理排序共用同一套 token 定义。
19
+ */
20
+
21
+ /** token 交替顺序:长 token 在前,避免被短 token 抢先切分。每次取新实例,避免共享 `lastIndex`。 */
22
+ const tokenPattern = (): RegExp => /YYYY|SSS|MM|DD|HH|mm|ss|timestamp|hash/g;
23
+
24
+ const DATE_TOKEN_WIDTH = { YYYY: 4, MM: 2, DD: 2, HH: 2, mm: 2, ss: 2, SSS: 3 } as const;
25
+
26
+ type DateToken = keyof typeof DATE_TOKEN_WIDTH;
27
+
28
+ /** 日期 token → `Date` 字段 */
29
+ const DATE_TOKEN_SLOT = {
30
+ YYYY: "year",
31
+ MM: "month",
32
+ DD: "day",
33
+ HH: "hour",
34
+ mm: "minute",
35
+ ss: "second",
36
+ SSS: "millisecond",
37
+ } as const satisfies Record<DateToken, string>;
38
+
39
+ type DateSlot = (typeof DATE_TOKEN_SLOT)[DateToken];
40
+
41
+ const TIME_TOKENS = ["timestamp", "YYYY", "MM", "DD", "HH", "mm", "ss", "SSS"] as const;
42
+
43
+ const AVAILABLE_TOKENS = ["hash", ...TIME_TOKENS];
44
+
45
+ /** 默认模式串:与历史默认目录名 `{commit}-{Date.now()}` 等价 */
46
+ export const DEFAULT_HASH_DIR_NAME_PATTERN = "hash-timestamp";
47
+
48
+ /** 目录名不允许出现的字符(路径分隔符、Windows 保留字符) */
49
+ const ILLEGAL_DIR_CHAR_PATTERN = /[\\/:*?"<>|]/;
50
+
51
+ const pad = (value: number, length = 2): string => String(value).padStart(length, "0");
52
+
53
+ function escapeRegExp(value: string): string {
54
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
55
+ }
56
+
57
+ function assertPatternValue(pattern: string): void {
58
+ if (pattern.trim() === "") {
59
+ throw new Error("[vite-config] hashDirName must be a non-empty string.");
60
+ }
61
+ }
62
+
63
+ /** 展开后的目录名必须留在 deployRoot 之下(模式串不能借字面文本跳出产物根目录) */
64
+ function assertSafeDirName(dirName: string, pattern: string): void {
65
+ const unsafe =
66
+ ILLEGAL_DIR_CHAR_PATTERN.test(dirName) ||
67
+ dirName.includes("..") ||
68
+ dirName.startsWith(".") ||
69
+ dirName.endsWith(".") ||
70
+ dirName !== dirName.trim();
71
+
72
+ if (unsafe) {
73
+ throw new Error(
74
+ `[vite-config] hashDirName "${pattern}" resolves to unsafe directory name "${dirName}".`,
75
+ );
76
+ }
77
+ }
78
+
79
+ /**
80
+ * 把目录名模式串展开为目录名。
81
+ * `timestamp` 与日期 token 共用同一个 `now`,保证描述同一时刻。
82
+ */
83
+ export function expandHashDirName(options: {
84
+ pattern: string;
85
+ commitHash: string;
86
+ now?: number;
87
+ }): string {
88
+ const { pattern, commitHash, now = Date.now() } = options;
89
+ assertPatternValue(pattern);
90
+
91
+ const date = new Date(now);
92
+ const values: Record<string, string> = {
93
+ hash: commitHash || "local",
94
+ timestamp: String(now),
95
+ YYYY: String(date.getFullYear()),
96
+ MM: pad(date.getMonth() + 1),
97
+ DD: pad(date.getDate()),
98
+ HH: pad(date.getHours()),
99
+ mm: pad(date.getMinutes()),
100
+ ss: pad(date.getSeconds()),
101
+ SSS: pad(date.getMilliseconds(), 3),
102
+ };
103
+
104
+ let timeMatched = false;
105
+ // 单次 replace:替换结果不会被二次扫描,避免 commit / 时间戳里的字符被再次展开
106
+ const dirName = pattern.replace(tokenPattern(), (token) => {
107
+ if ((TIME_TOKENS as readonly string[]).includes(token)) timeMatched = true;
108
+ return values[token] ?? token;
109
+ });
110
+
111
+ // 只含 commit(如 "hash")的目录名会让同一 commit 的多次构建互相覆盖,直接拒绝
112
+ if (!timeMatched) {
113
+ throw new Error(
114
+ `[vite-config] hashDirName "${pattern}" must contain a time token; available tokens: ${AVAILABLE_TOKENS.join(", ")}.`,
115
+ );
116
+ }
117
+
118
+ assertSafeDirName(dirName, pattern);
119
+
120
+ return dirName;
121
+ }
122
+
123
+ /**
124
+ * 模式串是否含可排序的时间 token(`timestamp` 或日期 token)。
125
+ * 清理器按目录名里的时间判断新旧,没有时间 token 就无从排序,必须让调用方提前报错。
126
+ */
127
+ export function hasTimeToken(pattern: string): boolean {
128
+ if (pattern.trim() === "") return false;
129
+
130
+ return [...pattern.matchAll(tokenPattern())].some((match) =>
131
+ (TIME_TOKENS as readonly string[]).includes(match[0]),
132
+ );
133
+ }
134
+
135
+ /**
136
+ * 由模式串编译出的历史目录匹配器:只认本模式串生成的目录名,并给出可排序时间戳。
137
+ */
138
+ export interface HashDirNameMatcher {
139
+ regex: RegExp;
140
+ /** 目录名 → 时间戳(毫秒);目录名不匹配本模式串时返回 `undefined` */
141
+ parseTimestamp(name: string): number | undefined;
142
+ }
143
+
144
+ /**
145
+ * 编译模式串:字面文本转义为 `^...$`,token 转为捕获组。
146
+ * - `timestamp` 存在时直接取其毫秒值排序;
147
+ * - 否则按日期 token 回推本地时间(缺省字段为 1970-01-01 00:00:00.000)。
148
+ * 模式串必须含时间 token(由 `expandHashDirName` 保证),故时间戳总是可解析。
149
+ */
150
+ export function compileHashDirNameMatcher(pattern: string): HashDirNameMatcher {
151
+ assertPatternValue(pattern);
152
+
153
+ let source = "^";
154
+ let cursor = 0;
155
+ let groupIndex = 1;
156
+ let epochGroup = -1;
157
+ const dateTokens: DateToken[] = [];
158
+
159
+ for (const match of pattern.matchAll(tokenPattern())) {
160
+ const index = match.index;
161
+ source += escapeRegExp(pattern.slice(cursor, index));
162
+
163
+ const token = match[0];
164
+ if (token === "hash") {
165
+ source += "(?:[0-9a-f]{12}|local)";
166
+ } else if (token === "timestamp") {
167
+ source += "(\\d{1,15})";
168
+ epochGroup = groupIndex;
169
+ groupIndex += 1;
170
+ } else {
171
+ const width = DATE_TOKEN_WIDTH[token as DateToken];
172
+ source += `(\\d{${width}})`;
173
+ dateTokens.push(token as DateToken);
174
+ groupIndex += 1;
175
+ }
176
+
177
+ cursor = index + token.length;
178
+ }
179
+ source += `${escapeRegExp(pattern.slice(cursor))}$`;
180
+
181
+ const regex = new RegExp(source);
182
+
183
+ return {
184
+ regex,
185
+ parseTimestamp(name: string): number | undefined {
186
+ const matched = regex.exec(name);
187
+ if (!matched) return undefined;
188
+
189
+ if (epochGroup > 0) {
190
+ const epoch = matched[epochGroup];
191
+ return epoch == null ? undefined : Number(epoch);
192
+ }
193
+ if (dateTokens.length === 0) return undefined;
194
+
195
+ const slots: Partial<Record<DateSlot, number>> = {};
196
+ dateTokens.forEach((token, position) => {
197
+ const raw = matched[position + 1];
198
+ if (raw != null) slots[DATE_TOKEN_SLOT[token]] = Number(raw);
199
+ });
200
+
201
+ return new Date(
202
+ slots.year ?? 1970,
203
+ (slots.month ?? 1) - 1,
204
+ slots.day ?? 1,
205
+ slots.hour ?? 0,
206
+ slots.minute ?? 0,
207
+ slots.second ?? 0,
208
+ slots.millisecond ?? 0,
209
+ ).getTime();
210
+ },
211
+ };
212
+ }
@@ -1,44 +1,72 @@
1
- import type { LessOptions } from "../types.ts";
2
-
3
- /**
4
- * Less 插件:把 webpack 遗留的 `~pkg/...` 导入解析到 node_modules。
5
- *
6
- * Less 自身不认识 `~`(那是 webpack `less-loader` 的约定:从 node_modules 解析);Vite 的
7
- * Less 预处理器也不处理 `~`,会回退到 Less 默认 FileManager 去查找 `node_modules/~pkg/...` 而失败。
8
- * 本插件注册一个 FileManager:仅当导入以 `~` 开头时拦截,去掉前缀后交给默认 FileManager 解析
9
- * (Vite 恒向 `less.render` 注入 `paths: ["node_modules"]`)。
10
- *
11
- * 第三方包(如 formily 系)自带 `@import "~antd/..."` 时尤其需要——消费方无法修改 node_modules。
12
- * @public
13
- */
14
- export function lessTildeResolutionPlugin() {
15
- return {
16
- install(less: any, pluginManager: any) {
17
- class TildeFileManager extends less.FileManager {
18
- supports(filename: string) {
19
- return filename.startsWith("~");
20
- }
21
- loadFile(filename: string, currentDirectory: string, options: any, environment: any) {
22
- // `~pkg/...` → `pkg/...`,让默认 FileManager 从 node_modules 解析
23
- return super.loadFile(filename.slice(1), currentDirectory, options, environment);
24
- }
25
- }
26
- pluginManager.addFileManager(new TildeFileManager());
27
- },
28
- };
29
- }
30
-
31
- /**
32
- * 组装 `css.preprocessorOptions.less`:映射 webpack `less-loader` 选项,
33
- * `less.resolveTilde: true` 时注入 `~` 解析插件(默认关闭)。
34
- * @public
35
- */
36
- export function buildLessOptions(less?: LessOptions) {
37
- const resolveTilde = less?.resolveTilde === true;
38
- return {
39
- ...(less?.additionalData != null ? { additionalData: less.additionalData } : {}),
40
- ...(less?.modifyVars != null ? { modifyVars: less.modifyVars } : {}),
41
- ...(less?.javascriptEnabled != null ? { javascriptEnabled: less.javascriptEnabled } : {}),
42
- ...(resolveTilde ? { plugins: [lessTildeResolutionPlugin()] } : {}),
43
- };
44
- }
1
+ import type { LessOptions } from "../types.ts";
2
+
3
+ /**
4
+ * less 插件注入的 FileManager 实例表面类型。less@4 不自带 TS 类型,按实际使用的最小面声明。
5
+ */
6
+ interface LessFileManagerInstance {
7
+ supports(filename: string): boolean;
8
+ loadFile(
9
+ filename: string,
10
+ currentDirectory: string,
11
+ options: unknown,
12
+ environment: unknown,
13
+ ): unknown;
14
+ }
15
+
16
+ /** less.js 传给插件 `install` 的 less 环境实例表面。 */
17
+ interface LessPluginHost {
18
+ FileManager: new (...args: unknown[]) => LessFileManagerInstance;
19
+ }
20
+
21
+ /** less.js 插件管理器表面。 */
22
+ interface LessPluginManager {
23
+ addFileManager(manager: LessFileManagerInstance): void;
24
+ }
25
+
26
+ /**
27
+ * Less 插件:把 webpack 遗留的 `~pkg/...` 导入解析到 node_modules。
28
+ *
29
+ * Less 自身不认识 `~`(那是 webpack `less-loader` 的约定:从 node_modules 解析);Vite 的
30
+ * Less 预处理器也不处理 `~`,会回退到 Less 默认 FileManager 去查找 `node_modules/~pkg/...` 而失败。
31
+ * 本插件注册一个 FileManager:仅当导入以 `~` 开头时拦截,去掉前缀后交给默认 FileManager 解析
32
+ * (Vite 恒向 `less.render` 注入 `paths: ["node_modules"]`)。
33
+ *
34
+ * 第三方包(如 formily 系)自带 `@import "~antd/..."` 时尤其需要——消费方无法修改 node_modules。
35
+ * @public
36
+ */
37
+ export function lessTildeResolutionPlugin() {
38
+ return {
39
+ install(less: LessPluginHost, pluginManager: LessPluginManager) {
40
+ class TildeFileManager extends less.FileManager {
41
+ override supports(filename: string) {
42
+ return filename.startsWith("~");
43
+ }
44
+ override loadFile(
45
+ filename: string,
46
+ currentDirectory: string,
47
+ options: unknown,
48
+ environment: unknown,
49
+ ) {
50
+ // `~pkg/...` → `pkg/...`,让默认 FileManager 从 node_modules 解析
51
+ return super.loadFile(filename.slice(1), currentDirectory, options, environment);
52
+ }
53
+ }
54
+ pluginManager.addFileManager(new TildeFileManager());
55
+ },
56
+ };
57
+ }
58
+
59
+ /**
60
+ * 组装 `css.preprocessorOptions.less`:映射 webpack `less-loader` 选项,
61
+ * `less.resolveTilde: true` 时注入 `~` 解析插件(默认关闭)。
62
+ * @public
63
+ */
64
+ export function buildLessOptions(less?: LessOptions) {
65
+ const resolveTilde = less?.resolveTilde === true;
66
+ return {
67
+ ...(less?.additionalData != null ? { additionalData: less.additionalData } : {}),
68
+ ...(less?.modifyVars != null ? { modifyVars: less.modifyVars } : {}),
69
+ ...(less?.javascriptEnabled != null ? { javascriptEnabled: less.javascriptEnabled } : {}),
70
+ ...(resolveTilde ? { plugins: [lessTildeResolutionPlugin()] } : {}),
71
+ };
72
+ }
@@ -1,40 +1,40 @@
1
- import type { PluginOption } from "vite";
2
-
3
- /** @public */
4
- export interface LifecyclePluginOptions {
5
- /** 构建开始(Vite `buildStart`)。仅同步。 */
6
- onRun?: () => void;
7
- /**
8
- * 产物写盘成功之后(`writeBundle` sequential post)。
9
- * 工厂中排在 Hash 根入口写入之后;Hash 写入失败不会调用。
10
- */
11
- onDone?: () => void | Promise<void>;
12
- }
13
-
14
- /**
15
- * 构建起止回调。`onDone` 使用 sequential post `writeBundle`,
16
- * 以便排在 Hash 部署等其它 post 写入之后。
17
- * @public
18
- */
19
- export function lifecyclePlugin(options: LifecyclePluginOptions = {}): PluginOption {
20
- const { onRun, onDone } = options;
21
-
22
- return {
23
- name: "build-lifecycle",
24
- enforce: "post",
25
- buildStart() {
26
- if (typeof onRun === "function") {
27
- onRun();
28
- }
29
- },
30
- writeBundle: {
31
- sequential: true,
32
- order: "post",
33
- async handler() {
34
- if (typeof onDone === "function") {
35
- await onDone();
36
- }
37
- },
38
- },
39
- };
40
- }
1
+ import type { PluginOption } from "vite";
2
+
3
+ /** @public */
4
+ export interface LifecyclePluginOptions {
5
+ /** 构建开始(Vite `buildStart`)。仅同步。 */
6
+ onRun?: () => void;
7
+ /**
8
+ * 产物写盘成功之后(`writeBundle` sequential post)。
9
+ * 工厂中排在 Hash 根入口写入之后;Hash 写入失败不会调用。
10
+ */
11
+ onDone?: () => void | Promise<void>;
12
+ }
13
+
14
+ /**
15
+ * 构建起止回调。`onDone` 使用 sequential post `writeBundle`,
16
+ * 以便排在 Hash 部署等其它 post 写入之后。
17
+ * @public
18
+ */
19
+ export function lifecyclePlugin(options: LifecyclePluginOptions = {}): PluginOption {
20
+ const { onRun, onDone } = options;
21
+
22
+ return {
23
+ name: "build-lifecycle",
24
+ enforce: "post",
25
+ buildStart() {
26
+ if (typeof onRun === "function") {
27
+ onRun();
28
+ }
29
+ },
30
+ writeBundle: {
31
+ sequential: true,
32
+ order: "post",
33
+ async handler() {
34
+ if (typeof onDone === "function") {
35
+ await onDone();
36
+ }
37
+ },
38
+ },
39
+ };
40
+ }
@@ -1,28 +1,28 @@
1
- import { copyPlugin } from "./copy.ts";
2
-
3
- import type { PluginOption } from "vite";
4
-
5
- /** @public */
6
- export interface PublicAssetsPluginOptions {
7
- /**
8
- * 源目录,相对项目 root。
9
- * @defaultValue "public"
10
- */
11
- dir?: string;
12
- }
13
-
14
- /**
15
- * 将 `public/**` 复制到产物 `public/` 子目录(保留目录结构),替代 Vite 默认 publicDir 根目录散落。
16
- * @public
17
- */
18
- export function publicAssetsPlugin(options: PublicAssetsPluginOptions = {}): PluginOption {
19
- const { dir = "public" } = options;
20
- return copyPlugin({
21
- targets: [
22
- {
23
- src: `${dir}/**/*`,
24
- dest: ".",
25
- },
26
- ],
27
- });
28
- }
1
+ import { copyPlugin } from "./copy.ts";
2
+
3
+ import type { PluginOption } from "vite";
4
+
5
+ /** @public */
6
+ export interface PublicAssetsPluginOptions {
7
+ /**
8
+ * 源目录,相对项目 root。
9
+ * @defaultValue "public"
10
+ */
11
+ dir?: string;
12
+ }
13
+
14
+ /**
15
+ * 将 `public/**` 复制到产物 `public/` 子目录(保留目录结构),替代 Vite 默认 publicDir 根目录散落。
16
+ * @public
17
+ */
18
+ export function publicAssetsPlugin(options: PublicAssetsPluginOptions = {}): PluginOption {
19
+ const { dir = "public" } = options;
20
+ return copyPlugin({
21
+ targets: [
22
+ {
23
+ src: `${dir}/**/*`,
24
+ dest: ".",
25
+ },
26
+ ],
27
+ });
28
+ }
@@ -1,34 +1,34 @@
1
- import { copyPlugin } from "./copy.ts";
2
-
3
- import type { PluginOption } from "vite";
4
-
5
- /** @public */
6
- export interface PublicConfigPluginOptions {
7
- /** 源 glob,如 `config/public-config/development/*` */
8
- sourceGlob: string;
9
- /**
10
- * 产物目标目录(可由消费方覆盖)。
11
- * @defaultValue "config"(站点根 `/config/`)
12
- * @example "public/config"
13
- */
14
- dest?: string;
15
- }
16
-
17
- /**
18
- * 将运行时 public-config 复制到产物目录(默认 `config/`,配合 `window.globalConfig`)。
19
- * @public
20
- */
21
- export function publicConfigPlugin(options: PublicConfigPluginOptions): PluginOption {
22
- const { sourceGlob, dest = "config" } = options;
23
- return copyPlugin({
24
- targets: [
25
- {
26
- src: sourceGlob,
27
- dest,
28
- rename: {
29
- stripBase: true,
30
- },
31
- },
32
- ],
33
- });
34
- }
1
+ import { copyPlugin } from "./copy.ts";
2
+
3
+ import type { PluginOption } from "vite";
4
+
5
+ /** @public */
6
+ export interface PublicConfigPluginOptions {
7
+ /** 源 glob,如 `config/public-config/development/*` */
8
+ sourceGlob: string;
9
+ /**
10
+ * 产物目标目录(可由消费方覆盖)。
11
+ * @defaultValue "config"(站点根 `/config/`)
12
+ * @example "public/config"
13
+ */
14
+ dest?: string;
15
+ }
16
+
17
+ /**
18
+ * 将运行时 public-config 复制到产物目录(默认 `config/`,配合 `window.globalConfig`)。
19
+ * @public
20
+ */
21
+ export function publicConfigPlugin(options: PublicConfigPluginOptions): PluginOption {
22
+ const { sourceGlob, dest = "config" } = options;
23
+ return copyPlugin({
24
+ targets: [
25
+ {
26
+ src: sourceGlob,
27
+ dest,
28
+ rename: {
29
+ stripBase: true,
30
+ },
31
+ },
32
+ ],
33
+ });
34
+ }
@@ -1,32 +1,32 @@
1
- import babel from "@rolldown/plugin-babel";
2
- import { reactCompilerPreset } from "@vitejs/plugin-react";
3
-
4
- import type { ReactCompilerMode } from "../types.ts";
5
- import type { PluginOption } from "vite";
6
-
7
- /** @public */
8
- export interface ReactCompilerPluginOptions {
9
- command: string;
10
- /**
11
- * - `true`:始终启用
12
- * - `"build-only"`:仅 build,且 `REACT_COMPILER=false` 可关
13
- * - `false`:关闭
14
- */
15
- mode?: ReactCompilerMode;
16
- }
17
-
18
- /**
19
- * React Compiler(babel preset)。默认仅生产构建启用。
20
- * @public
21
- */
22
- export function reactCompilerPlugin(options: ReactCompilerPluginOptions): PluginOption[] {
23
- const { command, mode = "build-only" } = options;
24
- if (mode === false) return [];
25
-
26
- const isBuild = command === "build";
27
- const enabled = mode === true ? true : isBuild && process.env.REACT_COMPILER !== "false";
28
-
29
- if (!enabled) return [];
30
-
31
- return [babel({ presets: [reactCompilerPreset()] })];
32
- }
1
+ import babel from "@rolldown/plugin-babel";
2
+ import { reactCompilerPreset } from "@vitejs/plugin-react";
3
+
4
+ import type { ReactCompilerMode } from "../types.ts";
5
+ import type { PluginOption } from "vite";
6
+
7
+ /** @public */
8
+ export interface ReactCompilerPluginOptions {
9
+ command: string;
10
+ /**
11
+ * - `true`:始终启用
12
+ * - `"build-only"`:仅 build,且 `REACT_COMPILER=false` 可关
13
+ * - `false`:关闭
14
+ */
15
+ mode?: ReactCompilerMode;
16
+ }
17
+
18
+ /**
19
+ * React Compiler(babel preset)。默认仅生产构建启用。
20
+ * @public
21
+ */
22
+ export function reactCompilerPlugin(options: ReactCompilerPluginOptions): PluginOption[] {
23
+ const { command, mode = "build-only" } = options;
24
+ if (mode === false) return [];
25
+
26
+ const isBuild = command === "build";
27
+ const enabled = mode === true ? true : isBuild && process.env.REACT_COMPILER !== "false";
28
+
29
+ if (!enabled) return [];
30
+
31
+ return [babel({ presets: [reactCompilerPreset()] })];
32
+ }
@@ -1,20 +1,20 @@
1
- import type { PluginOption } from "vite";
2
-
3
- /**
4
- * hash 部署场景下,把资源路径与 `import.meta.env.BASE_URL` 改写成相对部署目录。
5
- * @public
6
- */
7
- export function relativeBasePlugin(deployPath: string = "./"): PluginOption {
8
- return {
9
- name: "relative-base",
10
- transformIndexHtml(html: string) {
11
- return html
12
- .replace(/href="\.?\/assets\//g, `href="${deployPath}assets/`)
13
- .replace(/src="\.?\/assets\//g, `src="${deployPath}assets/`);
14
- },
15
- transform(code: string, id: string) {
16
- if (id.includes("node_modules")) return null;
17
- return code.replace(/import\.meta\.env\.BASE_URL/g, `'${deployPath}'`);
18
- },
19
- };
20
- }
1
+ import type { PluginOption } from "vite";
2
+
3
+ /**
4
+ * hash 部署场景下,把资源路径与 `import.meta.env.BASE_URL` 改写成相对部署目录。
5
+ * @public
6
+ */
7
+ export function relativeBasePlugin(deployPath: string = "./"): PluginOption {
8
+ return {
9
+ name: "relative-base",
10
+ transformIndexHtml(html: string) {
11
+ return html
12
+ .replace(/href="\.?\/assets\//g, `href="${deployPath}assets/`)
13
+ .replace(/src="\.?\/assets\//g, `src="${deployPath}assets/`);
14
+ },
15
+ transform(code: string, id: string) {
16
+ if (id.includes("node_modules")) return null;
17
+ return code.replace(/import\.meta\.env\.BASE_URL/g, `'${deployPath}'`);
18
+ },
19
+ };
20
+ }