@moluoxixi/vite-config 0.0.32 → 0.0.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/es/AutoRoutesPlugin/index.mjs +86 -0
- package/es/AutoRoutesPlugin/routeGenerator.mjs +123 -0
- package/es/_utils/base.mjs +8 -0
- package/es/_utils/dynamicImport.mjs +13 -0
- package/es/_utils/object.mjs +56 -0
- package/es/_utils/virtual.mjs +389 -0
- package/es/index.d.ts +2 -0
- package/es/index.mjs +3 -1190
- package/es/src/_utils/detectFramework.mjs +45 -0
- package/es/src/_utils/getEnv.mjs +21 -0
- package/es/src/constants/index.mjs +32 -0
- package/es/src/index.mjs +395 -0
- package/es/src/plugins/addScopedAndReplacePrefix.mjs +54 -0
- package/lib/AutoRoutesPlugin/index.cjs +86 -0
- package/lib/AutoRoutesPlugin/routeGenerator.cjs +123 -0
- package/lib/_utils/base.cjs +9 -0
- package/lib/_utils/dynamicImport.cjs +13 -0
- package/lib/_utils/object.cjs +56 -0
- package/lib/_utils/virtual.cjs +394 -0
- package/lib/index.cjs +9 -1215
- package/lib/index.d.ts +2 -0
- package/lib/src/_utils/detectFramework.cjs +48 -0
- package/lib/src/_utils/getEnv.cjs +25 -0
- package/lib/src/constants/index.cjs +32 -0
- package/lib/src/index.cjs +425 -0
- package/lib/src/plugins/addScopedAndReplacePrefix.cjs +54 -0
- package/package.json +24 -24
package/es/index.mjs
CHANGED
|
@@ -1,1193 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import fs from "node:fs";
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
import process$1 from "node:process";
|
|
7
|
-
import "vue";
|
|
8
|
-
import "dotenv";
|
|
9
|
-
import tailwindcss from "@tailwindcss/postcss";
|
|
10
|
-
import autoprefixer from "autoprefixer";
|
|
11
|
-
import { defineConfig, mergeConfig, normalizePath } from "vite";
|
|
12
|
-
import { createHtmlPlugin } from "vite-plugin-html";
|
|
13
|
-
import { debounce } from "lodash-es";
|
|
14
|
-
function getType(obj, type) {
|
|
15
|
-
{
|
|
16
|
-
return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase() === type.toLowerCase();
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
async function dynamicImport(modulePromise, exportName = "default") {
|
|
20
|
-
const module = await modulePromise;
|
|
21
|
-
if (exportName === "default") {
|
|
22
|
-
return module.default ?? module;
|
|
23
|
-
}
|
|
24
|
-
if (!(exportName in module)) {
|
|
25
|
-
throw new Error(`模块中不存在导出 "${exportName}"`);
|
|
26
|
-
}
|
|
27
|
-
return module[exportName];
|
|
28
|
-
}
|
|
29
|
-
function isObject(value) {
|
|
30
|
-
return Object.prototype.toString.call(value) === "[object Object]";
|
|
31
|
-
}
|
|
32
|
-
function deepMerge(target, source) {
|
|
33
|
-
if (!isObject(source)) {
|
|
34
|
-
return target;
|
|
35
|
-
}
|
|
36
|
-
return Object.keys(source).reduce((acc, key) => {
|
|
37
|
-
const sourceValue = source[key];
|
|
38
|
-
const targetValue = acc[key];
|
|
39
|
-
if (isObject(sourceValue) && isObject(targetValue)) {
|
|
40
|
-
acc[key] = deepMerge(targetValue, sourceValue);
|
|
41
|
-
} else if (isObject(sourceValue)) {
|
|
42
|
-
acc[key] = deepMerge({}, sourceValue);
|
|
43
|
-
} else {
|
|
44
|
-
acc[key] = sourceValue;
|
|
45
|
-
}
|
|
46
|
-
return acc;
|
|
47
|
-
}, { ...target });
|
|
48
|
-
}
|
|
49
|
-
function validateMutuallyExclusive(values, defaultKey) {
|
|
50
|
-
const keys = Object.keys(values);
|
|
51
|
-
const enabledKeys = [];
|
|
52
|
-
for (const key of keys) {
|
|
53
|
-
if (values[key] === true) {
|
|
54
|
-
enabledKeys.push(key);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
if (enabledKeys.length > 1) {
|
|
58
|
-
const keysStr = enabledKeys.join("、");
|
|
59
|
-
const allKeysStr = keys.join("、");
|
|
60
|
-
const selectedKey = enabledKeys.includes(defaultKey) ? defaultKey : enabledKeys[0];
|
|
61
|
-
console.warn(
|
|
62
|
-
`[validateMutuallyExclusive] ${allKeysStr} 只能启用一个,但当前启用了:${keysStr}。已自动选择:${String(selectedKey)}`
|
|
63
|
-
);
|
|
64
|
-
const result2 = {};
|
|
65
|
-
for (const key of keys) {
|
|
66
|
-
result2[key] = key === selectedKey;
|
|
67
|
-
}
|
|
68
|
-
return result2;
|
|
69
|
-
}
|
|
70
|
-
const hasEnabledKey = enabledKeys.length > 0;
|
|
71
|
-
const result = {};
|
|
72
|
-
for (const key of keys) {
|
|
73
|
-
if (!hasEnabledKey && defaultKey && key === defaultKey) {
|
|
74
|
-
result[key] = true;
|
|
75
|
-
} else {
|
|
76
|
-
result[key] = values[key] ?? false;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return result;
|
|
80
|
-
}
|
|
81
|
-
function detectFramework(config, rootDir) {
|
|
82
|
-
const root = rootDir || process$1.cwd();
|
|
83
|
-
const packageJsonPath = path.resolve(root, "package.json");
|
|
84
|
-
let vue = config.vue;
|
|
85
|
-
let react = config.react;
|
|
86
|
-
let vitepress = config.vitepress;
|
|
87
|
-
const hasExplicitFramework = vue === true || react === true || vitepress === true;
|
|
88
|
-
if (!hasExplicitFramework) {
|
|
89
|
-
let dependencies = {};
|
|
90
|
-
let devDependencies = {};
|
|
91
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
92
|
-
try {
|
|
93
|
-
const packageJsonContent = fs.readFileSync(packageJsonPath, "utf-8");
|
|
94
|
-
const packageJson = JSON.parse(packageJsonContent);
|
|
95
|
-
dependencies = packageJson.dependencies || {};
|
|
96
|
-
devDependencies = packageJson.devDependencies || {};
|
|
97
|
-
} catch (error) {
|
|
98
|
-
console.warn(`无法读取 package.json: ${packageJsonPath}`, error);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
if (vue === void 0) {
|
|
102
|
-
if (dependencies.vue || devDependencies.vue) {
|
|
103
|
-
vue = true;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
if (react === void 0 && vue !== true) {
|
|
107
|
-
if (dependencies.react || devDependencies.react) {
|
|
108
|
-
react = true;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
if (vitepress === void 0 && vue !== true && react !== true) {
|
|
112
|
-
if (dependencies.vitepress || devDependencies.vitepress) {
|
|
113
|
-
vitepress = true;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
return {
|
|
118
|
-
vue: vue ?? false,
|
|
119
|
-
react: react ?? false,
|
|
120
|
-
vitepress: vitepress ?? false
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
function changeHtmlClassPrefix(htmlString = "", oldPrefix = "", newPrefix = "") {
|
|
124
|
-
const regex = new RegExp(
|
|
125
|
-
`(class|style)\\s*:\\s*((["']((${oldPrefix}\\b)-).*["'])|((_normalizeClass|_normalizeStyle)\\(.*(${oldPrefix}\\b)-.*\\)))`,
|
|
126
|
-
"g"
|
|
127
|
-
);
|
|
128
|
-
return htmlString.replace(regex, (match = "") => {
|
|
129
|
-
return match.replace(oldPrefix, newPrefix);
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
function changeSelectorPrefix(cssString = "", oldPrefix = "", newPrefix = "") {
|
|
133
|
-
const regex = new RegExp(`(\\.${oldPrefix}\\b|#${oldPrefix}\\b|--${oldPrefix}\\b)`, "g");
|
|
134
|
-
return cssString.replace(regex, (match = "") => {
|
|
135
|
-
return match.replace(oldPrefix, newPrefix);
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
function addScopedAndReplacePrefixPlugin({
|
|
139
|
-
prefixScoped = "",
|
|
140
|
-
oldPrefix = "",
|
|
141
|
-
newPrefix = "",
|
|
142
|
-
useDevMode = false
|
|
143
|
-
}) {
|
|
144
|
-
let isProduction;
|
|
145
|
-
return {
|
|
146
|
-
name: "addScopedAndReplacePrefix",
|
|
147
|
-
configResolved(config) {
|
|
148
|
-
isProduction = config.command === "build" || config.isProduction;
|
|
149
|
-
},
|
|
150
|
-
transform(code = "", id = "") {
|
|
151
|
-
if (!isProduction && !useDevMode)
|
|
152
|
-
return code;
|
|
153
|
-
if (!oldPrefix || !newPrefix)
|
|
154
|
-
return code;
|
|
155
|
-
if (id.includes("node_modules"))
|
|
156
|
-
return code;
|
|
157
|
-
const cssLangs = ["css", "scss", "less", "stylus", "styl"];
|
|
158
|
-
let newCode = code;
|
|
159
|
-
if (id.endsWith(".vue")) {
|
|
160
|
-
newCode = changeHtmlClassPrefix(newCode, oldPrefix, newPrefix);
|
|
161
|
-
} else if (cssLangs.some((lang) => id.endsWith(`.${lang}`))) {
|
|
162
|
-
if (oldPrefix && newPrefix) {
|
|
163
|
-
newCode = changeSelectorPrefix(newCode, oldPrefix, newPrefix);
|
|
164
|
-
}
|
|
165
|
-
if (prefixScoped) {
|
|
166
|
-
newCode = `${newCode}${prefixScoped}{${newCode}}`;
|
|
167
|
-
}
|
|
168
|
-
return newCode;
|
|
169
|
-
}
|
|
170
|
-
return newCode;
|
|
171
|
-
}
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
async function getViteConfig(Config = {}, params) {
|
|
175
|
-
const config = typeof Config === "function" ? Config(params) : Config;
|
|
176
|
-
const { mode = "base" } = params || {};
|
|
177
|
-
const rootPath = config.rootPath || process.cwd();
|
|
178
|
-
const modeConfig = config.mode || {};
|
|
179
|
-
const baseConfig = modeConfig.base || {};
|
|
180
|
-
const currentModeConfig = modeConfig[mode] || {};
|
|
181
|
-
const viteEnv = { ...baseConfig, ...currentModeConfig };
|
|
182
|
-
const isDev = mode === "development";
|
|
183
|
-
const {
|
|
184
|
-
autoImport = config.autoImport ?? true,
|
|
185
|
-
autoComponent = config.autoComponent ?? true,
|
|
186
|
-
compression = config.compression ?? true,
|
|
187
|
-
imagemin = config.imagemin ?? true,
|
|
188
|
-
codeInspector = config.codeInspector ?? true,
|
|
189
|
-
port = config.port,
|
|
190
|
-
visualizer = config.visualizer ?? false,
|
|
191
|
-
autoRoutes = config.autoRoutes ?? false,
|
|
192
|
-
cdn = config.cdn ?? false,
|
|
193
|
-
pageRoutes = config.pageRoutes ?? false,
|
|
194
|
-
pwa = config.pwa ?? false,
|
|
195
|
-
devtools = config.devtools,
|
|
196
|
-
open = config.open,
|
|
197
|
-
qiankunDevMode = config.qiankunDevMode,
|
|
198
|
-
qiankun = config.qiankun,
|
|
199
|
-
namespace = config.namespace,
|
|
200
|
-
dropConsole = config.dropConsole,
|
|
201
|
-
vue: vueRaw = config.vue,
|
|
202
|
-
react: reactRaw = config.react,
|
|
203
|
-
vitepress: vitepressRaw = config.vitepress
|
|
204
|
-
} = viteEnv;
|
|
205
|
-
const frameworkResult = detectFramework(
|
|
206
|
-
{
|
|
207
|
-
vue: vueRaw,
|
|
208
|
-
react: reactRaw,
|
|
209
|
-
vitepress: vitepressRaw
|
|
210
|
-
},
|
|
211
|
-
rootPath
|
|
212
|
-
);
|
|
213
|
-
const { vue, react, vitepress } = validateMutuallyExclusive(
|
|
214
|
-
frameworkResult,
|
|
215
|
-
"vue"
|
|
216
|
-
);
|
|
217
|
-
const appTitle = config.appTitle;
|
|
218
|
-
const appCode = config.appCode;
|
|
219
|
-
const isVueOrVitepress = vue || vitepress;
|
|
220
|
-
const envSystemCode = isDev && !qiankunDevMode ? "el" : namespace ?? appCode;
|
|
221
|
-
const plugins = [
|
|
222
|
-
createHtmlPlugin({
|
|
223
|
-
inject: {
|
|
224
|
-
data: {
|
|
225
|
-
title: appTitle
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
})
|
|
229
|
-
];
|
|
230
|
-
if (vue) {
|
|
231
|
-
const pluginVue = await dynamicImport(import("@vitejs/plugin-vue"));
|
|
232
|
-
plugins.push(pluginVue());
|
|
233
|
-
}
|
|
234
|
-
if (react) {
|
|
235
|
-
const pluginReact = await dynamicImport(import("@vitejs/plugin-react"));
|
|
236
|
-
plugins.push(pluginReact());
|
|
237
|
-
}
|
|
238
|
-
if (isVueOrVitepress) {
|
|
239
|
-
const vueJsx = await dynamicImport(import("@vitejs/plugin-vue-jsx"));
|
|
240
|
-
plugins.push(vueJsx());
|
|
241
|
-
}
|
|
242
|
-
if (pageRoutes) {
|
|
243
|
-
const Pages = await dynamicImport(import("vite-plugin-pages"));
|
|
244
|
-
const extensions = [];
|
|
245
|
-
if (vue) {
|
|
246
|
-
extensions.push("vue");
|
|
247
|
-
}
|
|
248
|
-
if (react) {
|
|
249
|
-
extensions.push("tsx", "jsx");
|
|
250
|
-
}
|
|
251
|
-
plugins.push(Pages(
|
|
252
|
-
deepMerge(
|
|
253
|
-
{
|
|
254
|
-
dirs: "src/pages",
|
|
255
|
-
extensions,
|
|
256
|
-
exclude: [
|
|
257
|
-
"**/components/**",
|
|
258
|
-
"**/__tests__/**"
|
|
259
|
-
]
|
|
260
|
-
},
|
|
261
|
-
pageRoutes
|
|
262
|
-
)
|
|
263
|
-
));
|
|
264
|
-
}
|
|
265
|
-
if (isDev && devtools && isVueOrVitepress) {
|
|
266
|
-
const vueDevTools = await dynamicImport(import("vite-plugin-vue-devtools"));
|
|
267
|
-
plugins.push(vueDevTools());
|
|
268
|
-
}
|
|
269
|
-
if (autoImport && isVueOrVitepress) {
|
|
270
|
-
const AutoImport = await dynamicImport(import("unplugin-auto-import/vite"));
|
|
271
|
-
const ElementPlusResolverModule = await dynamicImport(import("unplugin-vue-components/resolvers"));
|
|
272
|
-
const { ElementPlusResolver } = ElementPlusResolverModule;
|
|
273
|
-
plugins.push(AutoImport(
|
|
274
|
-
deepMerge(
|
|
275
|
-
{
|
|
276
|
-
imports: ["vue"],
|
|
277
|
-
resolvers: [ElementPlusResolver()],
|
|
278
|
-
dts: path.resolve(rootPath, "./typings/auto-imports.d.ts")
|
|
279
|
-
},
|
|
280
|
-
autoImport
|
|
281
|
-
)
|
|
282
|
-
));
|
|
283
|
-
}
|
|
284
|
-
if (autoComponent && isVueOrVitepress) {
|
|
285
|
-
const Components = await dynamicImport(import("unplugin-vue-components/vite"));
|
|
286
|
-
const ElementPlusResolverModule = await dynamicImport(import("unplugin-vue-components/resolvers"));
|
|
287
|
-
const { ElementPlusResolver } = ElementPlusResolverModule;
|
|
288
|
-
plugins.push(Components(
|
|
289
|
-
deepMerge(
|
|
290
|
-
{
|
|
291
|
-
resolvers: [ElementPlusResolver()],
|
|
292
|
-
globs: [],
|
|
293
|
-
dts: path.resolve(rootPath, "./typings/components.d.ts")
|
|
294
|
-
},
|
|
295
|
-
autoComponent
|
|
296
|
-
)
|
|
297
|
-
));
|
|
298
|
-
}
|
|
299
|
-
if (compression) {
|
|
300
|
-
const viteCompression = await dynamicImport(import("vite-plugin-compression"));
|
|
301
|
-
const compressionPlugin = viteCompression;
|
|
302
|
-
plugins.push(compressionPlugin(
|
|
303
|
-
deepMerge(
|
|
304
|
-
{
|
|
305
|
-
algorithm: "brotliCompress",
|
|
306
|
-
verbose: true,
|
|
307
|
-
disable: false,
|
|
308
|
-
ext: ".gz",
|
|
309
|
-
threshold: 10240,
|
|
310
|
-
deleteOriginFile: false
|
|
311
|
-
},
|
|
312
|
-
compression
|
|
313
|
-
)
|
|
314
|
-
));
|
|
315
|
-
}
|
|
316
|
-
if (imagemin) {
|
|
317
|
-
const viteImagemin = await dynamicImport(import("vite-plugin-imagemin"));
|
|
318
|
-
const imageminPlugin = viteImagemin;
|
|
319
|
-
plugins.push(imageminPlugin(
|
|
320
|
-
deepMerge(
|
|
321
|
-
{
|
|
322
|
-
gifsicle: { optimizationLevel: 7, interlaced: false },
|
|
323
|
-
optipng: { optimizationLevel: 7 },
|
|
324
|
-
mozjpeg: { quality: 20 },
|
|
325
|
-
pngquant: { quality: [0.8, 0.9], speed: 4 },
|
|
326
|
-
svgo: {
|
|
327
|
-
plugins: [{ name: "removeViewBox" }, { name: "removeEmptyAttrs", active: false }]
|
|
328
|
-
}
|
|
329
|
-
},
|
|
330
|
-
imagemin
|
|
331
|
-
)
|
|
332
|
-
));
|
|
333
|
-
}
|
|
334
|
-
if (cdn) {
|
|
335
|
-
const importToCDN = await dynamicImport(import("vite-plugin-cdn-import"));
|
|
336
|
-
const { modules: modules2 } = await dynamicImport(Promise.resolve().then(() => index$1));
|
|
337
|
-
plugins.push(importToCDN(
|
|
338
|
-
deepMerge(
|
|
339
|
-
{
|
|
340
|
-
enableInDevMode: false,
|
|
341
|
-
prodUrl: "/{name}@{version}{path}",
|
|
342
|
-
modules: modules2,
|
|
343
|
-
generateScriptTag: (_name, scriptUrl) => {
|
|
344
|
-
const esmArr = ["esm", ".mjs"];
|
|
345
|
-
const isESM = esmArr.some((item) => scriptUrl.includes(item));
|
|
346
|
-
if (isESM) {
|
|
347
|
-
return {
|
|
348
|
-
attrs: {
|
|
349
|
-
src: scriptUrl,
|
|
350
|
-
type: "module",
|
|
351
|
-
crossorigin: "anonymous"
|
|
352
|
-
},
|
|
353
|
-
injectTo: "head"
|
|
354
|
-
};
|
|
355
|
-
} else {
|
|
356
|
-
return {
|
|
357
|
-
attrs: {
|
|
358
|
-
src: scriptUrl,
|
|
359
|
-
crossorigin: "anonymous"
|
|
360
|
-
},
|
|
361
|
-
injectTo: "head"
|
|
362
|
-
};
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
},
|
|
366
|
-
cdn
|
|
367
|
-
)
|
|
368
|
-
));
|
|
369
|
-
}
|
|
370
|
-
if (visualizer) {
|
|
371
|
-
const visualizerModule = await dynamicImport(import("rollup-plugin-visualizer"));
|
|
372
|
-
const { visualizer: visualizerPlugin } = visualizerModule;
|
|
373
|
-
plugins.push(visualizerPlugin(
|
|
374
|
-
deepMerge(
|
|
375
|
-
{
|
|
376
|
-
open: true
|
|
377
|
-
},
|
|
378
|
-
visualizer
|
|
379
|
-
)
|
|
380
|
-
));
|
|
381
|
-
}
|
|
382
|
-
if (pwa) {
|
|
383
|
-
const pwaModule = await dynamicImport(import("vite-plugin-pwa"));
|
|
384
|
-
const { VitePWA } = pwaModule;
|
|
385
|
-
plugins.push(VitePWA(
|
|
386
|
-
deepMerge(
|
|
387
|
-
{
|
|
388
|
-
strategies: "generateSW",
|
|
389
|
-
registerType: "autoUpdate",
|
|
390
|
-
// 开发模式下也启用
|
|
391
|
-
devOptions: {
|
|
392
|
-
enabled: true
|
|
393
|
-
},
|
|
394
|
-
includeAssets: ["favicon.ico", "apple-touch-icon.png", "mask-icon.svg"],
|
|
395
|
-
manifest: {
|
|
396
|
-
id: appCode ? `/${appCode}/` : "/",
|
|
397
|
-
start_url: appCode ? `/${appCode}/` : "/",
|
|
398
|
-
name: appTitle || "应用",
|
|
399
|
-
short_name: appTitle || "应用",
|
|
400
|
-
description: "渐进式 Web 应用",
|
|
401
|
-
display: "standalone",
|
|
402
|
-
background_color: "#ffffff",
|
|
403
|
-
theme_color: "#BA42BF"
|
|
404
|
-
}
|
|
405
|
-
},
|
|
406
|
-
pwa
|
|
407
|
-
)
|
|
408
|
-
));
|
|
409
|
-
}
|
|
410
|
-
if (isDev && codeInspector) {
|
|
411
|
-
const codeInspectorModule = await dynamicImport(import("code-inspector-plugin"));
|
|
412
|
-
const { codeInspectorPlugin } = codeInspectorModule;
|
|
413
|
-
plugins.push(codeInspectorPlugin(
|
|
414
|
-
deepMerge(
|
|
415
|
-
{
|
|
416
|
-
bundler: "vite",
|
|
417
|
-
showSwitch: true
|
|
418
|
-
},
|
|
419
|
-
codeInspector
|
|
420
|
-
)
|
|
421
|
-
));
|
|
422
|
-
}
|
|
423
|
-
if (qiankun) {
|
|
424
|
-
const qiankunPlugin = await dynamicImport(import("vite-plugin-qiankun"));
|
|
425
|
-
const qiankunPluginFn = qiankunPlugin;
|
|
426
|
-
plugins.push(qiankunPluginFn(envSystemCode || "el", { useDevMode: qiankunDevMode }));
|
|
427
|
-
if (appCode) {
|
|
428
|
-
plugins.push(addScopedAndReplacePrefixPlugin({
|
|
429
|
-
prefixScoped: `div[data-qiankun='${envSystemCode}']`,
|
|
430
|
-
oldPrefix: "el",
|
|
431
|
-
newPrefix: appCode,
|
|
432
|
-
useDevMode: qiankunDevMode
|
|
433
|
-
}));
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
if (autoRoutes && isVueOrVitepress) {
|
|
437
|
-
const AutoRoutesPlugin = await dynamicImport(Promise.resolve().then(() => index));
|
|
438
|
-
plugins.push(AutoRoutesPlugin(
|
|
439
|
-
deepMerge(
|
|
440
|
-
{
|
|
441
|
-
root: rootPath,
|
|
442
|
-
routeConfig: {
|
|
443
|
-
views: ["/src/views/**/index.vue", "!/src/views/**/components/*"],
|
|
444
|
-
examples: "/src/examples/**/index.vue",
|
|
445
|
-
componentExamples: {
|
|
446
|
-
glob: ["/src/components/**/Example.vue", "!/src/components/**/components/*"],
|
|
447
|
-
baseRoute: "组件示例"
|
|
448
|
-
}
|
|
449
|
-
},
|
|
450
|
-
dts: path.resolve(rootPath, "./typings/auto-routes.d.ts")
|
|
451
|
-
},
|
|
452
|
-
autoRoutes
|
|
453
|
-
)
|
|
454
|
-
));
|
|
455
|
-
}
|
|
456
|
-
const defaultConfig = {
|
|
457
|
-
plugins,
|
|
458
|
-
esbuild: {
|
|
459
|
-
pure: !isDev && dropConsole ? ["console.log", "console.info", "console.debug"] : []
|
|
460
|
-
},
|
|
461
|
-
build: {
|
|
462
|
-
sourcemap: isDev,
|
|
463
|
-
outDir: appCode || "dist",
|
|
464
|
-
cssCodeSplit: true,
|
|
465
|
-
chunkSizeWarningLimit: 1500,
|
|
466
|
-
minify: "esbuild",
|
|
467
|
-
rollupOptions: {
|
|
468
|
-
external: [],
|
|
469
|
-
output: {
|
|
470
|
-
globals: {},
|
|
471
|
-
chunkFileNames: "static/js/[name]-[hash].js",
|
|
472
|
-
entryFileNames: "static/js/[name]-[hash].js",
|
|
473
|
-
assetFileNames: "static/[ext]/[name]-[hash].[ext]",
|
|
474
|
-
manualChunks: (id) => {
|
|
475
|
-
if (id.includes("node_modules")) {
|
|
476
|
-
if (id.includes("lodash-es")) {
|
|
477
|
-
return "lodash-vendor";
|
|
478
|
-
}
|
|
479
|
-
if (id.includes("element-plus")) {
|
|
480
|
-
return "el-vendor";
|
|
481
|
-
}
|
|
482
|
-
if (id.includes("@vue") || id.includes("vue")) {
|
|
483
|
-
return "vue-vendor";
|
|
484
|
-
}
|
|
485
|
-
if (id.includes("antd") || id.includes("@ant-design")) {
|
|
486
|
-
return "antd-vendor";
|
|
487
|
-
}
|
|
488
|
-
if (id.includes("react-dom")) {
|
|
489
|
-
return "react-dom-vendor";
|
|
490
|
-
}
|
|
491
|
-
if (id.includes("react")) {
|
|
492
|
-
return "react-vendor";
|
|
493
|
-
}
|
|
494
|
-
return "vendor";
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
},
|
|
500
|
-
define: {
|
|
501
|
-
__SYSTEM_CODE__: JSON.stringify(envSystemCode),
|
|
502
|
-
process: deepMerge({
|
|
503
|
-
env: {
|
|
504
|
-
VUE_APP_VXE_ENV: "production"
|
|
505
|
-
}
|
|
506
|
-
}, process)
|
|
507
|
-
},
|
|
508
|
-
css: {
|
|
509
|
-
preprocessorOptions: {
|
|
510
|
-
scss: {
|
|
511
|
-
api: "modern-compiler"
|
|
512
|
-
}
|
|
513
|
-
},
|
|
514
|
-
postcss: {
|
|
515
|
-
plugins: [tailwindcss(), autoprefixer()]
|
|
516
|
-
},
|
|
517
|
-
devSourcemap: isDev
|
|
518
|
-
},
|
|
519
|
-
resolve: {
|
|
520
|
-
extensions: [".js", ".jsx", ".ts", ".tsx", ".vue"],
|
|
521
|
-
alias: {
|
|
522
|
-
"@": path.resolve(rootPath, "./src")
|
|
523
|
-
}
|
|
524
|
-
},
|
|
525
|
-
server: {
|
|
526
|
-
host: "0.0.0.0",
|
|
527
|
-
port,
|
|
528
|
-
open,
|
|
529
|
-
cors: true,
|
|
530
|
-
proxy: {}
|
|
531
|
-
}
|
|
532
|
-
};
|
|
533
|
-
if (!vitepress && appCode) {
|
|
534
|
-
defaultConfig.base = `/${appCode}`;
|
|
535
|
-
}
|
|
536
|
-
const viteConfig = typeof config.viteConfig === "function" ? config.viteConfig(params) : config.viteConfig;
|
|
537
|
-
const viteConfigPluginNames = ((viteConfig == null ? void 0 : viteConfig.plugins) || []).map((i) => {
|
|
538
|
-
const plugin = Array.isArray(i) ? i[0] : i;
|
|
539
|
-
return plugin == null ? void 0 : plugin.name;
|
|
540
|
-
}).filter((name) => Boolean(name));
|
|
541
|
-
const defaultPluginNamesMap = (defaultConfig.plugins || []).reduce((nameMap, i) => {
|
|
542
|
-
const plugin = Array.isArray(i) ? i[0] : i;
|
|
543
|
-
const name = plugin == null ? void 0 : plugin.name;
|
|
544
|
-
if (name) {
|
|
545
|
-
nameMap[name] = i;
|
|
546
|
-
}
|
|
547
|
-
return nameMap;
|
|
548
|
-
}, {});
|
|
549
|
-
const uniquePlugin = [];
|
|
550
|
-
Object.keys(defaultPluginNamesMap).forEach((name) => {
|
|
551
|
-
if (!viteConfigPluginNames.includes(name)) {
|
|
552
|
-
uniquePlugin.push(defaultPluginNamesMap[name]);
|
|
553
|
-
}
|
|
554
|
-
});
|
|
555
|
-
defaultConfig.plugins = uniquePlugin;
|
|
556
|
-
return mergeConfig(defaultConfig, viteConfig || {});
|
|
557
|
-
}
|
|
558
|
-
function createViteConfig(Config) {
|
|
559
|
-
return defineConfig(async (params) => await getViteConfig(Config, params));
|
|
560
|
-
}
|
|
561
|
-
function wrapperEnv(env) {
|
|
562
|
-
const result = {};
|
|
563
|
-
for (const key in env) {
|
|
564
|
-
if (Object.prototype.hasOwnProperty.call(env, key)) {
|
|
565
|
-
const value = env[key].trim();
|
|
566
|
-
if (value === "true" || value === "false") {
|
|
567
|
-
result[key] = value === "true";
|
|
568
|
-
} else if (!Number.isNaN(Number(value))) {
|
|
569
|
-
result[key] = Number(value);
|
|
570
|
-
} else if (value === "") {
|
|
571
|
-
result[key] = null;
|
|
572
|
-
} else {
|
|
573
|
-
result[key] = value;
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
return result;
|
|
578
|
-
}
|
|
579
|
-
function getCamelCase(str) {
|
|
580
|
-
return str.replace(/[-_]+/g, " ").replace(/(?:^|\s)\w/g, (match) => match.toUpperCase()).replace(/\s+/g, "");
|
|
581
|
-
}
|
|
582
|
-
function getCdnModules(modules2) {
|
|
583
|
-
function getPath(str) {
|
|
584
|
-
if (!str)
|
|
585
|
-
return "";
|
|
586
|
-
return str.startsWith("/") ? str : `/${str}`;
|
|
587
|
-
}
|
|
588
|
-
return modules2.map((item) => {
|
|
589
|
-
if (typeof item === "string") {
|
|
590
|
-
return {
|
|
591
|
-
name: item,
|
|
592
|
-
var: getCamelCase(item),
|
|
593
|
-
path: ""
|
|
594
|
-
};
|
|
595
|
-
} else {
|
|
596
|
-
return item;
|
|
597
|
-
}
|
|
598
|
-
}).map((item) => {
|
|
599
|
-
return {
|
|
600
|
-
name: item.name,
|
|
601
|
-
var: item.var || getCamelCase(item.name),
|
|
602
|
-
path: getPath(item.path),
|
|
603
|
-
css: getPath(item.css)
|
|
604
|
-
};
|
|
605
|
-
});
|
|
606
|
-
}
|
|
607
|
-
const modules = getCdnModules([]);
|
|
608
|
-
const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
609
|
-
__proto__: null,
|
|
610
|
-
modules
|
|
611
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
612
|
-
function resolvePatternsToAbsolute(patterns, rootDir) {
|
|
613
|
-
return patterns.map((p) => normalizePath(path.isAbsolute(p) ? p : path.resolve(rootDir, p)));
|
|
614
|
-
}
|
|
615
|
-
function extractStaticPrefixFromGlob(absPattern) {
|
|
616
|
-
const special = ["*", "?", "{", "}", "!", "(", ")", "[", "]"];
|
|
617
|
-
const idx = absPattern.split("").findIndex((ch) => special.includes(ch));
|
|
618
|
-
return idx === -1 ? absPattern : absPattern.slice(0, idx);
|
|
619
|
-
}
|
|
620
|
-
function createMatcher(prefixes) {
|
|
621
|
-
return (absFile) => prefixes.some((prefix) => absFile.startsWith(prefix));
|
|
622
|
-
}
|
|
623
|
-
class VirtualModuleState {
|
|
624
|
-
constructor() {
|
|
625
|
-
/** 标记服务器是否正在关闭,避免关闭阶段再触发无效操作 */
|
|
626
|
-
__publicField(this, "isServerClosing", false);
|
|
627
|
-
/** 标记初始化是否完成,初始化期间的变化会被延迟处理 */
|
|
628
|
-
__publicField(this, "isInitialized", false);
|
|
629
|
-
/** 标记初始化期间是否有文件变化,初始化完成后会处理这些变化 */
|
|
630
|
-
__publicField(this, "hasPendingChange", false);
|
|
631
|
-
/** HMR 热更新的防抖函数,lodash-es debounce 返回的函数有 cancel 方法,可以手动取消 */
|
|
632
|
-
__publicField(this, "hmrDebouncedInvalidate");
|
|
633
|
-
/** watchChange 钩子的防抖函数,用于清理模块缓存 */
|
|
634
|
-
__publicField(this, "watchChangeDebouncedClear");
|
|
635
|
-
/** 文件监听器的防抖函数 */
|
|
636
|
-
__publicField(this, "watcherDebouncedInvalidate");
|
|
637
|
-
}
|
|
638
|
-
/**
|
|
639
|
-
* 清理所有防抖定时器
|
|
640
|
-
* 在服务器关闭时调用,确保不会有待执行的防抖任务
|
|
641
|
-
*/
|
|
642
|
-
clearAll() {
|
|
643
|
-
var _a, _b, _c;
|
|
644
|
-
(_a = this.hmrDebouncedInvalidate) == null ? void 0 : _a.cancel();
|
|
645
|
-
(_b = this.watchChangeDebouncedClear) == null ? void 0 : _b.cancel();
|
|
646
|
-
(_c = this.watcherDebouncedInvalidate) == null ? void 0 : _c.cancel();
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
function invalidateModules(server, virtualModuleId, moduleCache) {
|
|
650
|
-
const ids = Array.from(moduleCache.keys()).filter(
|
|
651
|
-
(k) => k === virtualModuleId || k.startsWith(`${virtualModuleId}/`)
|
|
652
|
-
);
|
|
653
|
-
const mods = [];
|
|
654
|
-
for (const vid of ids) {
|
|
655
|
-
moduleCache.delete(vid);
|
|
656
|
-
const mod = server.moduleGraph.getModuleById(vid);
|
|
657
|
-
if (mod) {
|
|
658
|
-
server.moduleGraph.invalidateModule(mod);
|
|
659
|
-
mods.push(mod);
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
return mods;
|
|
663
|
-
}
|
|
664
|
-
function sendHmrUpdate(server, mods) {
|
|
665
|
-
var _a;
|
|
666
|
-
if (mods.length === 0) {
|
|
667
|
-
server == null ? void 0 : server.ws.send({ type: "full-reload" });
|
|
668
|
-
return;
|
|
669
|
-
}
|
|
670
|
-
try {
|
|
671
|
-
for (const mod of mods) {
|
|
672
|
-
try {
|
|
673
|
-
(_a = server.reloadModule) == null ? void 0 : _a.call(server, mod);
|
|
674
|
-
} catch {
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
server == null ? void 0 : server.ws.send({
|
|
678
|
-
type: "update",
|
|
679
|
-
updates: mods.map((mod) => ({
|
|
680
|
-
type: "js-update",
|
|
681
|
-
path: mod.url,
|
|
682
|
-
acceptedPath: mod.url,
|
|
683
|
-
timestamp: Date.now()
|
|
684
|
-
}))
|
|
685
|
-
});
|
|
686
|
-
} catch {
|
|
687
|
-
server == null ? void 0 : server.ws.send({ type: "full-reload" });
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
function setupFileWatcher(options) {
|
|
691
|
-
var _a;
|
|
692
|
-
const { server, watchPatterns, isWatchedPath, onInvalidate, debounceMs, onInitialized } = options;
|
|
693
|
-
let watcherReady = false;
|
|
694
|
-
let netReady = false;
|
|
695
|
-
let enabled = false;
|
|
696
|
-
const debouncedInvalidate = debounce(onInvalidate, debounceMs, {
|
|
697
|
-
trailing: true,
|
|
698
|
-
leading: false
|
|
699
|
-
});
|
|
700
|
-
const maybeEnable = () => {
|
|
701
|
-
var _a2;
|
|
702
|
-
if (enabled || !watcherReady || !netReady)
|
|
703
|
-
return;
|
|
704
|
-
enabled = true;
|
|
705
|
-
try {
|
|
706
|
-
if (watchPatterns.length > 0)
|
|
707
|
-
server.watcher.add(watchPatterns);
|
|
708
|
-
} catch {
|
|
709
|
-
}
|
|
710
|
-
const handleFileChange = (eventName, file) => {
|
|
711
|
-
if (eventName === "change" || eventName === "unlink" || eventName === "unlinkDir" || watcherReady && (eventName === "add" || eventName === "addDir")) {
|
|
712
|
-
const abs = normalizePath(
|
|
713
|
-
path.isAbsolute(file) ? file : path.resolve(server.config.root, file)
|
|
714
|
-
);
|
|
715
|
-
if (isWatchedPath(abs))
|
|
716
|
-
debouncedInvalidate();
|
|
717
|
-
}
|
|
718
|
-
};
|
|
719
|
-
server.watcher.on("all", handleFileChange);
|
|
720
|
-
const cleanup = () => {
|
|
721
|
-
debouncedInvalidate.cancel();
|
|
722
|
-
server.watcher.off("all", handleFileChange);
|
|
723
|
-
};
|
|
724
|
-
server.watcher.once("close", cleanup);
|
|
725
|
-
(_a2 = server.httpServer) == null ? void 0 : _a2.once("close", cleanup);
|
|
726
|
-
onInitialized == null ? void 0 : onInitialized();
|
|
727
|
-
};
|
|
728
|
-
server.watcher.once("ready", () => {
|
|
729
|
-
watcherReady = true;
|
|
730
|
-
maybeEnable();
|
|
731
|
-
});
|
|
732
|
-
(_a = server.httpServer) == null ? void 0 : _a.once("listening", () => {
|
|
733
|
-
netReady = true;
|
|
734
|
-
maybeEnable();
|
|
735
|
-
});
|
|
736
|
-
const wsAny = server.ws;
|
|
737
|
-
if (typeof (wsAny == null ? void 0 : wsAny.on) === "function") {
|
|
738
|
-
const connectionHandler = () => {
|
|
739
|
-
var _a2, _b;
|
|
740
|
-
netReady = true;
|
|
741
|
-
maybeEnable();
|
|
742
|
-
try {
|
|
743
|
-
(_a2 = wsAny.off) == null ? void 0 : _a2.call(wsAny, "connection", connectionHandler);
|
|
744
|
-
} catch {
|
|
745
|
-
}
|
|
746
|
-
try {
|
|
747
|
-
(_b = wsAny.removeListener) == null ? void 0 : _b.call(wsAny, "connection", connectionHandler);
|
|
748
|
-
} catch {
|
|
749
|
-
}
|
|
750
|
-
};
|
|
751
|
-
wsAny.on("connection", connectionHandler);
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
function writeDtsFile(config, rootDir, dts, generateDts) {
|
|
755
|
-
if (dts === false || !generateDts)
|
|
756
|
-
return;
|
|
757
|
-
try {
|
|
758
|
-
const dtsPath = typeof dts === "string" ? path.isAbsolute(dts) ? dts : path.resolve(rootDir, dts) : path.resolve(rootDir, "./src/typings/virtual-module.d.ts");
|
|
759
|
-
const content = generateDts({ config });
|
|
760
|
-
const normalized = normalizePath(dtsPath);
|
|
761
|
-
const dir = path.dirname(normalized);
|
|
762
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
763
|
-
fs.writeFileSync(normalized, content, "utf-8");
|
|
764
|
-
} catch {
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
function callUserHook(hook, context, ...args) {
|
|
768
|
-
if (!hook)
|
|
769
|
-
return void 0;
|
|
770
|
-
if (typeof hook === "function") {
|
|
771
|
-
return hook.call(context, ...args);
|
|
772
|
-
} else if (hook.handler) {
|
|
773
|
-
return hook.handler.call(context, ...args);
|
|
774
|
-
}
|
|
775
|
-
return void 0;
|
|
776
|
-
}
|
|
777
|
-
function createVirtualPlugin(userConfig) {
|
|
778
|
-
const {
|
|
779
|
-
virtualModuleId,
|
|
780
|
-
dts,
|
|
781
|
-
root,
|
|
782
|
-
watch,
|
|
783
|
-
debounceMs = 2e3,
|
|
784
|
-
...restConfig
|
|
785
|
-
} = userConfig;
|
|
786
|
-
const VIRTUAL_MODULE_ID = virtualModuleId;
|
|
787
|
-
const {
|
|
788
|
-
resolveId,
|
|
789
|
-
load,
|
|
790
|
-
configResolved,
|
|
791
|
-
configureServer,
|
|
792
|
-
handleHotUpdate,
|
|
793
|
-
watchChange,
|
|
794
|
-
generateModule,
|
|
795
|
-
generateDts,
|
|
796
|
-
...restHooks
|
|
797
|
-
} = restConfig;
|
|
798
|
-
const moduleCache = /* @__PURE__ */ new Map();
|
|
799
|
-
const state = new VirtualModuleState();
|
|
800
|
-
let resolvedViteConfig;
|
|
801
|
-
let watchPatterns = [];
|
|
802
|
-
let isWatchedPath = () => true;
|
|
803
|
-
const performInvalidate = (server) => {
|
|
804
|
-
if (state.isServerClosing)
|
|
805
|
-
return;
|
|
806
|
-
const mods = invalidateModules(server, VIRTUAL_MODULE_ID, moduleCache);
|
|
807
|
-
sendHmrUpdate(server, mods);
|
|
808
|
-
};
|
|
809
|
-
const handleFileChange = (server) => {
|
|
810
|
-
if (!state.isInitialized) {
|
|
811
|
-
state.hasPendingChange = true;
|
|
812
|
-
return;
|
|
813
|
-
}
|
|
814
|
-
performInvalidate(server);
|
|
815
|
-
};
|
|
816
|
-
return {
|
|
817
|
-
/**
|
|
818
|
-
* 解析虚拟模块 ID
|
|
819
|
-
* 当 import 语句引用虚拟模块时,Vite 会调用此方法
|
|
820
|
-
* @param args - resolveId 的所有参数
|
|
821
|
-
* @returns 如果匹配虚拟模块 ID,返回该 ID;否则返回 undefined
|
|
822
|
-
*/
|
|
823
|
-
resolveId(...args) {
|
|
824
|
-
const [id] = args;
|
|
825
|
-
if (id === VIRTUAL_MODULE_ID || id.startsWith(`${VIRTUAL_MODULE_ID}/`))
|
|
826
|
-
return id;
|
|
827
|
-
return callUserHook(resolveId, this, ...args);
|
|
828
|
-
},
|
|
829
|
-
/**
|
|
830
|
-
* 配置解析完成钩子
|
|
831
|
-
* 在 Vite 配置解析完成后调用,用于初始化监听路径和生成类型声明文件
|
|
832
|
-
* @param args - configResolved 的所有参数
|
|
833
|
-
*/
|
|
834
|
-
configResolved(...args) {
|
|
835
|
-
const [config] = args;
|
|
836
|
-
resolvedViteConfig = config;
|
|
837
|
-
const rootDir = root || config.root;
|
|
838
|
-
const patterns = Array.isArray(watch) ? watch : watch ? [watch] : [];
|
|
839
|
-
watchPatterns = resolvePatternsToAbsolute(patterns, rootDir);
|
|
840
|
-
const watchPrefixes = watchPatterns.map(extractStaticPrefixFromGlob);
|
|
841
|
-
isWatchedPath = watchPrefixes.length === 0 ? () => true : createMatcher(watchPrefixes);
|
|
842
|
-
writeDtsFile(config, rootDir, dts, generateDts);
|
|
843
|
-
callUserHook(configResolved, this, ...args);
|
|
844
|
-
},
|
|
845
|
-
/**
|
|
846
|
-
* 配置开发服务器钩子
|
|
847
|
-
* 在开发服务器启动时调用,用于设置文件监听、信号处理和清理逻辑
|
|
848
|
-
* @param args - configureServer 的所有参数
|
|
849
|
-
*/
|
|
850
|
-
configureServer(...args) {
|
|
851
|
-
var _a;
|
|
852
|
-
const [server] = args;
|
|
853
|
-
const handleSignal = () => {
|
|
854
|
-
var _a2;
|
|
855
|
-
if (state.isServerClosing)
|
|
856
|
-
return;
|
|
857
|
-
state.isServerClosing = true;
|
|
858
|
-
Promise.resolve((_a2 = server == null ? void 0 : server.close) == null ? void 0 : _a2.call(server)).finally(() => {
|
|
859
|
-
try {
|
|
860
|
-
process$1.exit(0);
|
|
861
|
-
} catch {
|
|
862
|
-
}
|
|
863
|
-
});
|
|
864
|
-
};
|
|
865
|
-
process$1.once("SIGINT", handleSignal);
|
|
866
|
-
process$1.once("SIGTERM", handleSignal);
|
|
867
|
-
(_a = server.httpServer) == null ? void 0 : _a.once("close", () => {
|
|
868
|
-
state.isServerClosing = true;
|
|
869
|
-
state.clearAll();
|
|
870
|
-
});
|
|
871
|
-
setupFileWatcher({
|
|
872
|
-
server,
|
|
873
|
-
watchPatterns,
|
|
874
|
-
isWatchedPath,
|
|
875
|
-
onInvalidate: () => handleFileChange(server),
|
|
876
|
-
debounceMs,
|
|
877
|
-
onInitialized: () => {
|
|
878
|
-
state.isInitialized = true;
|
|
879
|
-
if (state.hasPendingChange) {
|
|
880
|
-
state.hasPendingChange = false;
|
|
881
|
-
setTimeout(() => {
|
|
882
|
-
if (!state.isServerClosing)
|
|
883
|
-
performInvalidate(server);
|
|
884
|
-
}, 0);
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
});
|
|
888
|
-
callUserHook(configureServer, this, ...args);
|
|
889
|
-
},
|
|
890
|
-
/**
|
|
891
|
-
* 处理热更新钩子
|
|
892
|
-
* 当 Vite 检测到文件变化时调用,用于触发虚拟模块的失效和更新
|
|
893
|
-
* @param args - handleHotUpdate 的所有参数
|
|
894
|
-
* @returns 空数组,表示不阻止其他插件的处理
|
|
895
|
-
* @remarks
|
|
896
|
-
* - 使用防抖机制避免频繁触发
|
|
897
|
-
* - 初始化期间的变化会被延迟处理
|
|
898
|
-
* - 只处理匹配监听路径的文件变化
|
|
899
|
-
*/
|
|
900
|
-
handleHotUpdate(...args) {
|
|
901
|
-
const [ctx] = args;
|
|
902
|
-
const { server } = ctx;
|
|
903
|
-
const rootDir = root || (resolvedViteConfig == null ? void 0 : resolvedViteConfig.root) || server.config.root;
|
|
904
|
-
const abs = normalizePath(
|
|
905
|
-
path.isAbsolute(ctx.file) ? ctx.file : path.resolve(rootDir, ctx.file)
|
|
906
|
-
);
|
|
907
|
-
if (!isWatchedPath(abs) || state.isServerClosing)
|
|
908
|
-
return;
|
|
909
|
-
if (!state.isInitialized) {
|
|
910
|
-
state.hasPendingChange = true;
|
|
911
|
-
return [];
|
|
912
|
-
}
|
|
913
|
-
if (!state.hmrDebouncedInvalidate) {
|
|
914
|
-
state.hmrDebouncedInvalidate = debounce(
|
|
915
|
-
() => {
|
|
916
|
-
if (state.isServerClosing)
|
|
917
|
-
return;
|
|
918
|
-
performInvalidate(server);
|
|
919
|
-
},
|
|
920
|
-
debounceMs,
|
|
921
|
-
{ trailing: true, leading: false }
|
|
922
|
-
);
|
|
923
|
-
}
|
|
924
|
-
state.hmrDebouncedInvalidate();
|
|
925
|
-
return callUserHook(handleHotUpdate, this, ...args) || [];
|
|
926
|
-
},
|
|
927
|
-
/**
|
|
928
|
-
* 监听文件变化钩子
|
|
929
|
-
* 当 Vite 的依赖预构建或文件系统检测到变化时调用
|
|
930
|
-
* 主要用于清理模块缓存,让下次加载时重新生成
|
|
931
|
-
* @param args - watchChange 的所有参数
|
|
932
|
-
* @remarks
|
|
933
|
-
* - 与 handleHotUpdate 不同,此钩子主要用于清理缓存,不触发 HMR
|
|
934
|
-
* - 使用防抖机制避免频繁清理
|
|
935
|
-
* - 初始化期间的变化会被延迟处理
|
|
936
|
-
*/
|
|
937
|
-
watchChange(...args) {
|
|
938
|
-
try {
|
|
939
|
-
const [id] = args;
|
|
940
|
-
const rootDir = root || (resolvedViteConfig == null ? void 0 : resolvedViteConfig.root) || process$1.cwd();
|
|
941
|
-
const absId = normalizePath(path.isAbsolute(id) ? id : path.resolve(rootDir, id));
|
|
942
|
-
if (!isWatchedPath(absId) || state.isServerClosing) {
|
|
943
|
-
return;
|
|
944
|
-
}
|
|
945
|
-
if (!state.isInitialized) {
|
|
946
|
-
state.hasPendingChange = true;
|
|
947
|
-
return;
|
|
948
|
-
}
|
|
949
|
-
if (!state.watchChangeDebouncedClear) {
|
|
950
|
-
state.watchChangeDebouncedClear = debounce(
|
|
951
|
-
() => {
|
|
952
|
-
if (state.isServerClosing)
|
|
953
|
-
return;
|
|
954
|
-
for (const k of Array.from(moduleCache.keys())) {
|
|
955
|
-
if (k === VIRTUAL_MODULE_ID || k.startsWith(`${VIRTUAL_MODULE_ID}/`))
|
|
956
|
-
moduleCache.delete(k);
|
|
957
|
-
}
|
|
958
|
-
},
|
|
959
|
-
debounceMs,
|
|
960
|
-
{ trailing: true, leading: false }
|
|
961
|
-
);
|
|
962
|
-
}
|
|
963
|
-
state.watchChangeDebouncedClear();
|
|
964
|
-
return callUserHook(watchChange, this, ...args);
|
|
965
|
-
} catch {
|
|
966
|
-
}
|
|
967
|
-
},
|
|
968
|
-
/**
|
|
969
|
-
* 加载虚拟模块内容
|
|
970
|
-
* 当 import 语句引用虚拟模块时,Vite 会调用此方法获取模块代码
|
|
971
|
-
* @param args - load 的所有参数
|
|
972
|
-
* @returns 模块代码字符串,如果 ID 不匹配则返回 undefined
|
|
973
|
-
* @remarks
|
|
974
|
-
* - 支持同步和异步的 generateModule 函数
|
|
975
|
-
* - 生成的代码会被缓存,直到模块被失效
|
|
976
|
-
* - 子路径导入(如 'virtual:routes/sub')会传入完整 ID 给 generateModule
|
|
977
|
-
*/
|
|
978
|
-
async load(...args) {
|
|
979
|
-
const [id] = args;
|
|
980
|
-
if (id === VIRTUAL_MODULE_ID || id.startsWith(`${VIRTUAL_MODULE_ID}/`)) {
|
|
981
|
-
const code = getType(generateModule, "asyncfunction") ? await generateModule({ id, config: resolvedViteConfig }) : generateModule({ id, config: resolvedViteConfig });
|
|
982
|
-
moduleCache.set(id, code);
|
|
983
|
-
return code;
|
|
984
|
-
}
|
|
985
|
-
return await callUserHook(load, this, ...args);
|
|
986
|
-
},
|
|
987
|
-
// 使用 rest 参数包含所有其他未使用的钩子(包括 name, transform, enforce 等)
|
|
988
|
-
...restHooks
|
|
989
|
-
};
|
|
990
|
-
}
|
|
991
|
-
function cleanRoute(route) {
|
|
992
|
-
const cleaned = { ...route };
|
|
993
|
-
if (cleaned.children) {
|
|
994
|
-
if (Array.isArray(cleaned.children) && cleaned.children.length > 0) {
|
|
995
|
-
cleaned.children = cleaned.children.map(cleanRoute);
|
|
996
|
-
} else {
|
|
997
|
-
delete cleaned.children;
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
return cleaned;
|
|
1001
|
-
}
|
|
1002
|
-
function findParentRouteHandle(modules2, parentPath) {
|
|
1003
|
-
for (const route of modules2) {
|
|
1004
|
-
if (route.path === parentPath) {
|
|
1005
|
-
return route;
|
|
1006
|
-
}
|
|
1007
|
-
if (route.children) {
|
|
1008
|
-
const found = findParentRouteHandle(route.children, parentPath);
|
|
1009
|
-
if (found)
|
|
1010
|
-
return found;
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
|
-
return void 0;
|
|
1014
|
-
}
|
|
1015
|
-
function parseModulePath(modulePath) {
|
|
1016
|
-
const pathArr = modulePath.split("/").filter((item) => item && !item.includes("."));
|
|
1017
|
-
if (pathArr.at(-1) === "src") {
|
|
1018
|
-
pathArr.pop();
|
|
1019
|
-
}
|
|
1020
|
-
const componentName = pathArr.at(-1);
|
|
1021
|
-
const path2 = `/${pathArr.join("/")}`;
|
|
1022
|
-
const parentPath = `/${pathArr.slice(0, -1).join("/")}`;
|
|
1023
|
-
return { pathArr, componentName, path: path2, parentPath };
|
|
1024
|
-
}
|
|
1025
|
-
function processComponent(componentLoader, componentName, eager) {
|
|
1026
|
-
if (eager) {
|
|
1027
|
-
return {
|
|
1028
|
-
component: componentLoader,
|
|
1029
|
-
metaTitle: (componentLoader == null ? void 0 : componentLoader.name) || componentName
|
|
1030
|
-
};
|
|
1031
|
-
}
|
|
1032
|
-
return {
|
|
1033
|
-
component: typeof componentLoader === "function" ? componentLoader : componentLoader,
|
|
1034
|
-
metaTitle: componentName
|
|
1035
|
-
};
|
|
1036
|
-
}
|
|
1037
|
-
function generateRoutes(files, prefix = "", baseRoute, eager = false) {
|
|
1038
|
-
const newBaseRoute = typeof baseRoute === "string" ? { name: baseRoute } : baseRoute;
|
|
1039
|
-
const modules2 = newBaseRoute ? [newBaseRoute] : [];
|
|
1040
|
-
const fileKeys = Object.keys(files);
|
|
1041
|
-
if (fileKeys.length === 0) {
|
|
1042
|
-
return [];
|
|
1043
|
-
}
|
|
1044
|
-
return fileKeys.sort((a, b) => {
|
|
1045
|
-
const aLength = a.split("/").length;
|
|
1046
|
-
const bLength = b.split("/").length;
|
|
1047
|
-
return bLength > aLength ? -1 : 1;
|
|
1048
|
-
}).reduce((modules22 = [], modulePath) => {
|
|
1049
|
-
const componentLoader = files[modulePath];
|
|
1050
|
-
if (!componentLoader || modulePath === "install") {
|
|
1051
|
-
return modules22;
|
|
1052
|
-
}
|
|
1053
|
-
const { path: path2, parentPath, componentName } = parseModulePath(modulePath);
|
|
1054
|
-
if (!componentName) {
|
|
1055
|
-
return modules22;
|
|
1056
|
-
}
|
|
1057
|
-
let parentRoute;
|
|
1058
|
-
if (newBaseRoute) {
|
|
1059
|
-
newBaseRoute.children = newBaseRoute.children || [];
|
|
1060
|
-
newBaseRoute.name = newBaseRoute.name || prefix;
|
|
1061
|
-
newBaseRoute.path = `/${(newBaseRoute.path || parentPath).split("/").filter((item) => item && !item.includes(".")).join("/")}`;
|
|
1062
|
-
parentRoute = newBaseRoute;
|
|
1063
|
-
} else {
|
|
1064
|
-
parentRoute = findParentRouteHandle(modules22, parentPath);
|
|
1065
|
-
}
|
|
1066
|
-
const { component, metaTitle } = processComponent(componentLoader, componentName, eager);
|
|
1067
|
-
const routeItem = {
|
|
1068
|
-
path: path2,
|
|
1069
|
-
name: componentName,
|
|
1070
|
-
meta: {
|
|
1071
|
-
title: metaTitle
|
|
1072
|
-
},
|
|
1073
|
-
component
|
|
1074
|
-
};
|
|
1075
|
-
if (parentRoute) {
|
|
1076
|
-
if (!parentRoute.children) {
|
|
1077
|
-
parentRoute.children = [];
|
|
1078
|
-
}
|
|
1079
|
-
parentRoute.children.push(routeItem);
|
|
1080
|
-
} else {
|
|
1081
|
-
modules22.push(routeItem);
|
|
1082
|
-
}
|
|
1083
|
-
return modules22;
|
|
1084
|
-
}, modules2).map(cleanRoute).filter((route) => {
|
|
1085
|
-
return !(route.children && Array.isArray(route.children) && route.children.length === 0);
|
|
1086
|
-
});
|
|
1087
|
-
}
|
|
1088
|
-
function findDefaultRouteHandle(routes) {
|
|
1089
|
-
var _a, _b, _c;
|
|
1090
|
-
if (!routes || routes.length === 0) {
|
|
1091
|
-
return "";
|
|
1092
|
-
}
|
|
1093
|
-
for (const route of routes) {
|
|
1094
|
-
if ((_a = route.meta) == null ? void 0 : _a.default) {
|
|
1095
|
-
return route.path || "";
|
|
1096
|
-
}
|
|
1097
|
-
if ((_b = route.children) == null ? void 0 : _b.length) {
|
|
1098
|
-
const childPath = findDefaultRouteHandle(route.children);
|
|
1099
|
-
if (childPath) {
|
|
1100
|
-
return childPath;
|
|
1101
|
-
}
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1104
|
-
return ((_c = routes[0]) == null ? void 0 : _c.path) || "";
|
|
1105
|
-
}
|
|
1106
|
-
function extractGlob(globVal) {
|
|
1107
|
-
return globVal.glob || globVal;
|
|
1108
|
-
}
|
|
1109
|
-
function getEagerOption(globVal, globalEager) {
|
|
1110
|
-
return globVal.eager ?? globalEager ?? false;
|
|
1111
|
-
}
|
|
1112
|
-
function generateImportCode(varName, glob, eager) {
|
|
1113
|
-
if (eager) {
|
|
1114
|
-
return `const ${varName} = import.meta.glob(${JSON.stringify(glob)}, { eager: true, import: 'default' });
|
|
1115
|
-
`;
|
|
1116
|
-
}
|
|
1117
|
-
return `const ${varName} = import.meta.glob(${JSON.stringify(glob)});
|
|
1118
|
-
`;
|
|
1119
|
-
}
|
|
1120
|
-
function createAutoRoutesPlugin({ routeConfig, virtualModuleId, dts, root, eager: globalEager }) {
|
|
1121
|
-
const VIRTUAL_MODULE_ID = virtualModuleId || "virtual:auto-routes";
|
|
1122
|
-
const watchGlobs = Object.values(routeConfig).flatMap((globVal) => {
|
|
1123
|
-
const g = extractGlob(globVal);
|
|
1124
|
-
return Array.isArray(g) ? g : [g];
|
|
1125
|
-
});
|
|
1126
|
-
return createVirtualPlugin(
|
|
1127
|
-
{
|
|
1128
|
-
name: "vite-plugin-auto-routes",
|
|
1129
|
-
virtualModuleId: VIRTUAL_MODULE_ID,
|
|
1130
|
-
dts,
|
|
1131
|
-
root,
|
|
1132
|
-
watch: watchGlobs,
|
|
1133
|
-
enforce: "pre",
|
|
1134
|
-
// 生成虚拟模块代码:仅负责产出字符串,监听/HMR/缓存由工厂统一处理
|
|
1135
|
-
generateModule: () => {
|
|
1136
|
-
const imports = [];
|
|
1137
|
-
const routes = [];
|
|
1138
|
-
Object.entries(routeConfig).forEach(([prefix, globVal], index2) => {
|
|
1139
|
-
const varName = `files${index2}`;
|
|
1140
|
-
const glob = extractGlob(globVal);
|
|
1141
|
-
const eager = getEagerOption(globVal, globalEager);
|
|
1142
|
-
const baseRoute = globVal.baseRoute;
|
|
1143
|
-
const baseRouteParam = baseRoute !== void 0 ? JSON.stringify(baseRoute) : "undefined";
|
|
1144
|
-
imports.push(generateImportCode(varName, glob, eager));
|
|
1145
|
-
routes.push(`...generateRoutes(${varName}, '${prefix}',${baseRouteParam}, ${eager})`);
|
|
1146
|
-
});
|
|
1147
|
-
const routesCode = routes.length > 0 ? `[${routes.join(",\n")}]` : "[]";
|
|
1148
|
-
return `
|
|
1149
|
-
${imports.join("\n")}
|
|
1150
|
-
${findParentRouteHandle}
|
|
1151
|
-
${parseModulePath}
|
|
1152
|
-
${processComponent}
|
|
1153
|
-
${cleanRoute}
|
|
1154
|
-
${findDefaultRouteHandle}
|
|
1155
|
-
|
|
1156
|
-
const findParentRoute = ${findParentRouteHandle}
|
|
1157
|
-
// 用于routes
|
|
1158
|
-
const generateRoutes = ${generateRoutes};
|
|
1159
|
-
// 用于导出
|
|
1160
|
-
const findDefaultRoute = ${findDefaultRouteHandle};
|
|
1161
|
-
|
|
1162
|
-
const routes = ${routesCode}.flat().filter(Boolean);
|
|
1163
|
-
|
|
1164
|
-
export { routes, findDefaultRoute };
|
|
1165
|
-
export default routes;
|
|
1166
|
-
`;
|
|
1167
|
-
},
|
|
1168
|
-
// 生成类型声明文件
|
|
1169
|
-
generateDts: () => `// 此文件由ViteConfig自动生成,请勿手动修改
|
|
1170
|
-
declare module 'virtual:auto-routes' {
|
|
1171
|
-
interface RouteModule {
|
|
1172
|
-
path: string
|
|
1173
|
-
name: string
|
|
1174
|
-
meta?: any
|
|
1175
|
-
component: () => Promise<any>
|
|
1176
|
-
children?: RouteModule[]
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
|
-
const routes: RouteModule[]
|
|
1180
|
-
const findDefaultRoute: (routes: any[]) => string
|
|
1181
|
-
export { findDefaultRoute, routes }
|
|
1182
|
-
export default routes
|
|
1183
|
-
}`
|
|
1184
|
-
}
|
|
1185
|
-
);
|
|
1186
|
-
}
|
|
1187
|
-
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1188
|
-
__proto__: null,
|
|
1189
|
-
default: createAutoRoutesPlugin
|
|
1190
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
1
|
+
import { createViteConfig } from "./src/index.mjs";
|
|
2
|
+
import { getViteConfig } from "./src/index.mjs";
|
|
3
|
+
import { wrapperEnv } from "./src/_utils/getEnv.mjs";
|
|
1191
4
|
export {
|
|
1192
5
|
createViteConfig as ViteConfig,
|
|
1193
6
|
createViteConfig as default,
|