@fchc8/vite-plugin-multi-page 1.4.2 → 1.5.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.
- package/dist/cli.js +93 -68
- package/dist/index.d.mts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +20 -39
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +20 -39
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -56,7 +56,11 @@ function hasCustomConfig() {
|
|
|
56
56
|
async function loadUserConfig(context) {
|
|
57
57
|
const customConfig = await loadCustomConfig();
|
|
58
58
|
if (customConfig) {
|
|
59
|
-
|
|
59
|
+
const result = customConfig(context);
|
|
60
|
+
if (!result) {
|
|
61
|
+
return {};
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
60
64
|
}
|
|
61
65
|
return null;
|
|
62
66
|
}
|
|
@@ -136,6 +140,56 @@ var init_config_loader = __esm({
|
|
|
136
140
|
}
|
|
137
141
|
});
|
|
138
142
|
|
|
143
|
+
// src/defaults.ts
|
|
144
|
+
var defaults_exports = {};
|
|
145
|
+
__export(defaults_exports, {
|
|
146
|
+
DEFAULT_CONFIG: () => DEFAULT_CONFIG,
|
|
147
|
+
isEmptyConfig: () => isEmptyConfig,
|
|
148
|
+
mergeWithDefaults: () => mergeWithDefaults
|
|
149
|
+
});
|
|
150
|
+
function mergeWithDefaults(userConfig) {
|
|
151
|
+
if (!userConfig) {
|
|
152
|
+
return { ...DEFAULT_CONFIG };
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
entry: userConfig.entry ?? DEFAULT_CONFIG.entry,
|
|
156
|
+
exclude: userConfig.exclude ?? DEFAULT_CONFIG.exclude,
|
|
157
|
+
template: userConfig.template ?? DEFAULT_CONFIG.template,
|
|
158
|
+
placeholder: userConfig.placeholder ?? DEFAULT_CONFIG.placeholder,
|
|
159
|
+
debug: userConfig.debug ?? DEFAULT_CONFIG.debug,
|
|
160
|
+
strategies: userConfig.strategies ?? DEFAULT_CONFIG.strategies,
|
|
161
|
+
pageConfigs: userConfig.pageConfigs ?? DEFAULT_CONFIG.pageConfigs,
|
|
162
|
+
__forceBuildStrategy: userConfig.__forceBuildStrategy
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function isEmptyConfig(config) {
|
|
166
|
+
if (Object.keys(config).length === 0) {
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
const hasValidEntry = config.entry && config.entry !== DEFAULT_CONFIG.entry;
|
|
170
|
+
const hasValidStrategies = config.strategies && Object.keys(config.strategies).length > 0;
|
|
171
|
+
const hasValidPageConfigs = config.pageConfigs && (typeof config.pageConfigs === "function" || Object.keys(config.pageConfigs).length > 0);
|
|
172
|
+
return !hasValidEntry && !hasValidStrategies && !hasValidPageConfigs;
|
|
173
|
+
}
|
|
174
|
+
var DEFAULT_CONFIG;
|
|
175
|
+
var init_defaults = __esm({
|
|
176
|
+
"src/defaults.ts"() {
|
|
177
|
+
"use strict";
|
|
178
|
+
init_cjs_shims();
|
|
179
|
+
DEFAULT_CONFIG = {
|
|
180
|
+
entry: "src/pages/**/*.{ts,js}",
|
|
181
|
+
exclude: [],
|
|
182
|
+
template: "index.html",
|
|
183
|
+
placeholder: "{{ENTRY_FILE}}",
|
|
184
|
+
debug: false,
|
|
185
|
+
strategies: {
|
|
186
|
+
default: {}
|
|
187
|
+
},
|
|
188
|
+
pageConfigs: {}
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
139
193
|
// src/cli.ts
|
|
140
194
|
var cli_exports = {};
|
|
141
195
|
__export(cli_exports, {
|
|
@@ -158,56 +212,39 @@ var fs = __toESM(require("fs"));
|
|
|
158
212
|
// src/file-filter.ts
|
|
159
213
|
init_cjs_shims();
|
|
160
214
|
var path = __toESM(require("path"));
|
|
161
|
-
function filterEntryFiles(files, entry, exclude,
|
|
215
|
+
function filterEntryFiles(files, entry, exclude, _log) {
|
|
162
216
|
const result = [];
|
|
163
217
|
const nameToFile = /* @__PURE__ */ new Map();
|
|
164
218
|
let basePattern = entry.replace(/\/\*.*$/, "");
|
|
165
219
|
if (!basePattern || basePattern === entry) {
|
|
166
220
|
basePattern = path.dirname(entry.split("*")[0]);
|
|
167
221
|
}
|
|
168
|
-
log("\u57FA\u7840\u76EE\u5F55\u6A21\u5F0F:", basePattern);
|
|
169
222
|
const candidateFiles = [];
|
|
170
223
|
for (const file of files) {
|
|
171
224
|
if (exclude.includes(file)) {
|
|
172
|
-
log(`\u8DF3\u8FC7\u6392\u9664\u6587\u4EF6: ${file}`);
|
|
173
225
|
continue;
|
|
174
226
|
}
|
|
175
227
|
const relativePath = path.relative(basePattern, file);
|
|
176
228
|
const pathParts = relativePath.split(path.sep);
|
|
177
|
-
log(`\u5904\u7406\u6587\u4EF6: ${file}`);
|
|
178
|
-
log(`\u76F8\u5BF9\u8DEF\u5F84: ${relativePath}`);
|
|
179
|
-
log(`\u8DEF\u5F84\u90E8\u5206: ${pathParts}`);
|
|
180
229
|
if (pathParts.length === 1) {
|
|
181
230
|
const fileName = pathParts[0];
|
|
182
231
|
const name = path.basename(fileName, path.extname(fileName));
|
|
183
232
|
candidateFiles.push({ name, file, priority: 1 });
|
|
184
|
-
log(`\u{1F4C4} \u7B2C\u4E00\u7EA7\u6587\u4EF6: ${file} -> ${name}.html (\u4F18\u5148\u7EA7: 1)`);
|
|
185
233
|
} else if (pathParts.length >= 2) {
|
|
186
234
|
const fileName = path.basename(file, path.extname(file));
|
|
187
235
|
const dirName = pathParts[0];
|
|
188
236
|
if (fileName === "main") {
|
|
189
237
|
candidateFiles.push({ name: dirName, file, priority: 2 });
|
|
190
|
-
log(`\u{1F4C1} \u76EE\u5F55main\u6587\u4EF6: ${file} -> ${dirName}.html (\u4F18\u5148\u7EA7: 2)`);
|
|
191
|
-
} else {
|
|
192
|
-
log(`\u274C \u8DF3\u8FC7\u6587\u4EF6: ${file} (\u4E0D\u662Fmain\u6587\u4EF6)`);
|
|
193
238
|
}
|
|
194
|
-
} else {
|
|
195
|
-
log(`\u274C \u8DF3\u8FC7\u6587\u4EF6: ${file} (\u8DEF\u5F84\u5C42\u7EA7\u4E0D\u7B26\u5408)`);
|
|
196
239
|
}
|
|
197
240
|
}
|
|
198
241
|
for (const candidate of candidateFiles) {
|
|
199
242
|
const existing = nameToFile.get(candidate.name);
|
|
200
243
|
if (!existing) {
|
|
201
244
|
nameToFile.set(candidate.name, { file: candidate.file, priority: candidate.priority });
|
|
202
|
-
log(`\u2705 \u6DFB\u52A0\u9875\u9762: ${candidate.name} -> ${candidate.file}`);
|
|
203
245
|
} else {
|
|
204
246
|
if (candidate.priority > existing.priority) {
|
|
205
247
|
nameToFile.set(candidate.name, { file: candidate.file, priority: candidate.priority });
|
|
206
|
-
log(
|
|
207
|
-
`\u{1F504} \u66FF\u6362\u9875\u9762: ${candidate.name} -> ${candidate.file} (\u66FF\u6362 ${existing.file}, \u76EE\u5F55\u4F18\u5148)`
|
|
208
|
-
);
|
|
209
|
-
} else {
|
|
210
|
-
log(`\u26A0\uFE0F \u51B2\u7A81\u8DF3\u8FC7: ${candidate.name} -> ${candidate.file} (\u4FDD\u7559 ${existing.file})`);
|
|
211
248
|
}
|
|
212
249
|
}
|
|
213
250
|
}
|
|
@@ -225,7 +262,6 @@ function getPageConfig(pageConfigs, context, log) {
|
|
|
225
262
|
if (typeof pageConfigs === "function") {
|
|
226
263
|
const result = pageConfigs(context);
|
|
227
264
|
if (result) {
|
|
228
|
-
log(`\u51FD\u6570\u914D\u7F6E\u5339\u914D\u9875\u9762 ${context.pageName}:`, result);
|
|
229
265
|
}
|
|
230
266
|
return result;
|
|
231
267
|
}
|
|
@@ -297,16 +333,20 @@ function parseArgs() {
|
|
|
297
333
|
const args = process.argv.slice(2);
|
|
298
334
|
const viteBuildArgs = [];
|
|
299
335
|
let debug = false;
|
|
336
|
+
let cwd;
|
|
300
337
|
for (let i = 0; i < args.length; i++) {
|
|
301
338
|
const arg = args[i];
|
|
302
339
|
if (arg === "--debug") {
|
|
303
340
|
debug = true;
|
|
341
|
+
} else if (arg === "--cwd") {
|
|
342
|
+
cwd = args[++i];
|
|
304
343
|
} else if (arg === "--help" || arg === "-h") {
|
|
305
344
|
console.log(`
|
|
306
345
|
\u4F7F\u7528\u65B9\u6CD5: vite-multi-page-build [\u9009\u9879]
|
|
307
346
|
|
|
308
347
|
\u9009\u9879:
|
|
309
348
|
--debug \u542F\u7528\u8C03\u8BD5\u6A21\u5F0F
|
|
349
|
+
--cwd <dir> \u6307\u5B9A\u5DE5\u4F5C\u76EE\u5F55
|
|
310
350
|
--help, -h \u663E\u793A\u5E2E\u52A9\u4FE1\u606F
|
|
311
351
|
|
|
312
352
|
\u5176\u4ED6\u6240\u6709\u53C2\u6570\u5C06\u4F20\u9012\u7ED9 vite build \u547D\u4EE4
|
|
@@ -314,60 +354,32 @@ function parseArgs() {
|
|
|
314
354
|
\u793A\u4F8B:
|
|
315
355
|
vite-multi-page-build
|
|
316
356
|
vite-multi-page-build --debug
|
|
357
|
+
vite-multi-page-build --cwd example
|
|
317
358
|
vite-multi-page-build --host --port 3000
|
|
318
359
|
vite-multi-page-build --mode production --debug
|
|
319
360
|
`);
|
|
320
361
|
process.exit(0);
|
|
321
|
-
} else {
|
|
362
|
+
} else if (arg !== "build") {
|
|
322
363
|
viteBuildArgs.push(arg);
|
|
323
364
|
}
|
|
324
365
|
}
|
|
325
|
-
return { viteBuildArgs, debug };
|
|
366
|
+
return { viteBuildArgs, debug, cwd };
|
|
326
367
|
}
|
|
327
368
|
async function loadViteConfig() {
|
|
328
369
|
const { loadUserConfig: loadUserConfig2, hasCustomConfig: hasCustomConfig2 } = await Promise.resolve().then(() => (init_config_loader(), config_loader_exports));
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
console.log("
|
|
339
|
-
console.log("export default (context) => {");
|
|
340
|
-
console.log(" const { mode, command, isCLI } = context;");
|
|
341
|
-
console.log(' const isProduction = mode === "production";');
|
|
342
|
-
console.log(" ");
|
|
343
|
-
console.log(" return {");
|
|
344
|
-
console.log(' entry: "src/pages/**/*.{ts,js}",');
|
|
345
|
-
console.log(' template: "index.html",');
|
|
346
|
-
console.log(' placeholder: "{{ENTRY_FILE}}",');
|
|
347
|
-
console.log(" strategies: {");
|
|
348
|
-
console.log(" default: {");
|
|
349
|
-
console.log(" define: { IS_DEFAULT: true },");
|
|
350
|
-
console.log(" build: { sourcemap: !isProduction },");
|
|
351
|
-
console.log(" },");
|
|
352
|
-
console.log(" },");
|
|
353
|
-
console.log(" pageConfigs: (pageContext) => ({");
|
|
354
|
-
console.log(' strategy: "default",');
|
|
355
|
-
console.log(" }),");
|
|
356
|
-
console.log(" };");
|
|
357
|
-
console.log("};");
|
|
358
|
-
console.log("```");
|
|
359
|
-
process.exit(1);
|
|
360
|
-
}
|
|
361
|
-
const userConfig = await loadUserConfig2({
|
|
362
|
-
mode: "production",
|
|
363
|
-
command: "build",
|
|
364
|
-
isCLI: true
|
|
365
|
-
});
|
|
366
|
-
if (!userConfig) {
|
|
367
|
-
console.error("\u274C \u914D\u7F6E\u6587\u4EF6\u52A0\u8F7D\u5931\u8D25\uFF01");
|
|
368
|
-
process.exit(1);
|
|
370
|
+
const { mergeWithDefaults: mergeWithDefaults2 } = await Promise.resolve().then(() => (init_defaults(), defaults_exports));
|
|
371
|
+
let userConfig = null;
|
|
372
|
+
if (hasCustomConfig2()) {
|
|
373
|
+
userConfig = await loadUserConfig2({
|
|
374
|
+
mode: "production",
|
|
375
|
+
command: "build",
|
|
376
|
+
isCLI: true
|
|
377
|
+
});
|
|
378
|
+
} else {
|
|
379
|
+
console.log("\u2139\uFE0F \u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E");
|
|
369
380
|
}
|
|
370
|
-
|
|
381
|
+
const finalConfig = mergeWithDefaults2(userConfig);
|
|
382
|
+
return finalConfig;
|
|
371
383
|
}
|
|
372
384
|
function buildStrategy(strategy, viteBuildArgs, debug) {
|
|
373
385
|
return new Promise((resolve4) => {
|
|
@@ -519,8 +531,11 @@ async function mergeResults(results, debug) {
|
|
|
519
531
|
}
|
|
520
532
|
}
|
|
521
533
|
log("\u2705 \u6784\u5EFA\u7ED3\u679C\u5408\u5E76\u5B8C\u6210");
|
|
522
|
-
log(`\u{1F4C1}
|
|
534
|
+
log(`\u{1F4C1} \u751F\u6210\u9875\u9762: ${htmlFiles.join(", ")}`);
|
|
523
535
|
log(`\u{1F4E6} \u8D44\u6E90\u76EE\u5F55: dist/assets/`);
|
|
536
|
+
log(
|
|
537
|
+
`\u{1F527} \u5904\u7406\u7B56\u7565: ${results.filter((r) => r.success).map((r) => r.strategy).join(", ")}`
|
|
538
|
+
);
|
|
524
539
|
}
|
|
525
540
|
async function cleanupTempFiles(debug) {
|
|
526
541
|
const log = debug ? console.log.bind(console, "[cleanup]") : () => {
|
|
@@ -586,9 +601,18 @@ async function cleanup(strategies, debug) {
|
|
|
586
601
|
log("\u2705 \u6E05\u7406\u5B8C\u6210");
|
|
587
602
|
}
|
|
588
603
|
async function main() {
|
|
589
|
-
const { viteBuildArgs, debug } = parseArgs();
|
|
604
|
+
const { viteBuildArgs, debug, cwd } = parseArgs();
|
|
590
605
|
const log = debug ? console.log.bind(console, "[main]") : () => {
|
|
591
606
|
};
|
|
607
|
+
if (cwd) {
|
|
608
|
+
const targetDir = path4.resolve(process.cwd(), cwd);
|
|
609
|
+
if (!fs3.existsSync(targetDir)) {
|
|
610
|
+
console.error(`\u274C \u6307\u5B9A\u7684\u76EE\u5F55\u4E0D\u5B58\u5728: ${targetDir}`);
|
|
611
|
+
process.exit(1);
|
|
612
|
+
}
|
|
613
|
+
process.chdir(targetDir);
|
|
614
|
+
log(`\u5207\u6362\u5DE5\u4F5C\u76EE\u5F55\u5230: ${targetDir}`);
|
|
615
|
+
}
|
|
592
616
|
try {
|
|
593
617
|
log("\u{1F680} \u5F00\u59CB\u591A\u7B56\u7565\u6784\u5EFA...");
|
|
594
618
|
log("\u{1F4CB} \u52A0\u8F7D\u914D\u7F6E...");
|
|
@@ -626,12 +650,13 @@ async function main() {
|
|
|
626
650
|
log("\u{1F4E6} \u5408\u5E76\u6784\u5EFA\u7ED3\u679C...");
|
|
627
651
|
await mergeResults(results, debug);
|
|
628
652
|
await cleanup(strategies, debug);
|
|
653
|
+
const successfulResults = results.filter((r) => r.success);
|
|
654
|
+
const htmlFiles = fs3.readdirSync(path4.resolve(process.cwd(), "dist")).filter((file) => file.endsWith(".html"));
|
|
629
655
|
console.log(`
|
|
630
656
|
\u{1F389} \u6240\u6709\u7B56\u7565\u6784\u5EFA\u6210\u529F\uFF01`);
|
|
631
657
|
console.log(`\u{1F4C1} \u6784\u5EFA\u7ED3\u679C\u4F4D\u4E8E: dist/`);
|
|
632
|
-
console.log(
|
|
633
|
-
|
|
634
|
-
);
|
|
658
|
+
console.log(`\u{1F310} \u751F\u6210\u7684\u9875\u9762: ${htmlFiles.join(", ")}`);
|
|
659
|
+
console.log(`\u{1F4E6} \u6784\u5EFA\u7B56\u7565: ${successfulResults.map((r) => r.strategy).join(", ")}`);
|
|
635
660
|
} catch (error) {
|
|
636
661
|
console.error("\u274C \u6784\u5EFA\u5931\u8D25:", error instanceof Error ? error.message : error);
|
|
637
662
|
process.exit(1);
|
package/dist/index.d.mts
CHANGED
|
@@ -58,6 +58,11 @@ declare function generateBuildConfig(options: BuildConfigOptions): Record<string
|
|
|
58
58
|
*/
|
|
59
59
|
declare function getAvailableStrategies(options: BuildConfigOptions): string[];
|
|
60
60
|
|
|
61
|
+
/**
|
|
62
|
+
* 合并用户配置和默认配置
|
|
63
|
+
*/
|
|
64
|
+
declare function mergeWithDefaults(userConfig: MultiPageOptions | null | undefined): MultiPageOptions;
|
|
65
|
+
|
|
61
66
|
declare function viteMultiPage(transform?: ConfigTransformFunction): Plugin;
|
|
62
67
|
|
|
63
|
-
export { type ConfigFunction, type ConfigTransformFunction, type Options, type PageConfig, type PageContext, type PluginContext, viteMultiPage as default, defineConfig, defineConfigTransform, generateBuildConfig, getAvailableStrategies, viteMultiPage };
|
|
68
|
+
export { type ConfigFunction, type ConfigTransformFunction, type Options, type PageConfig, type PageContext, type PluginContext, viteMultiPage as default, defineConfig, defineConfigTransform, generateBuildConfig, getAvailableStrategies, mergeWithDefaults, viteMultiPage };
|
package/dist/index.d.ts
CHANGED
|
@@ -58,6 +58,11 @@ declare function generateBuildConfig(options: BuildConfigOptions): Record<string
|
|
|
58
58
|
*/
|
|
59
59
|
declare function getAvailableStrategies(options: BuildConfigOptions): string[];
|
|
60
60
|
|
|
61
|
+
/**
|
|
62
|
+
* 合并用户配置和默认配置
|
|
63
|
+
*/
|
|
64
|
+
declare function mergeWithDefaults(userConfig: MultiPageOptions | null | undefined): MultiPageOptions;
|
|
65
|
+
|
|
61
66
|
declare function viteMultiPage(transform?: ConfigTransformFunction): Plugin;
|
|
62
67
|
|
|
63
|
-
export { type ConfigFunction, type ConfigTransformFunction, type Options, type PageConfig, type PageContext, type PluginContext, viteMultiPage as default, defineConfig, defineConfigTransform, generateBuildConfig, getAvailableStrategies, viteMultiPage };
|
|
68
|
+
export { type ConfigFunction, type ConfigTransformFunction, type Options, type PageConfig, type PageContext, type PluginContext, viteMultiPage as default, defineConfig, defineConfigTransform, generateBuildConfig, getAvailableStrategies, mergeWithDefaults, viteMultiPage };
|
package/dist/index.js
CHANGED
|
@@ -35,6 +35,7 @@ __export(src_exports, {
|
|
|
35
35
|
defineConfigTransform: () => defineConfigTransform,
|
|
36
36
|
generateBuildConfig: () => generateBuildConfig,
|
|
37
37
|
getAvailableStrategies: () => getAvailableStrategies,
|
|
38
|
+
mergeWithDefaults: () => mergeWithDefaults,
|
|
38
39
|
viteMultiPage: () => viteMultiPage
|
|
39
40
|
});
|
|
40
41
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -48,56 +49,39 @@ var import_glob = require("glob");
|
|
|
48
49
|
|
|
49
50
|
// src/file-filter.ts
|
|
50
51
|
var path = __toESM(require("path"));
|
|
51
|
-
function filterEntryFiles(files, entry, exclude,
|
|
52
|
+
function filterEntryFiles(files, entry, exclude, _log) {
|
|
52
53
|
const result = [];
|
|
53
54
|
const nameToFile = /* @__PURE__ */ new Map();
|
|
54
55
|
let basePattern = entry.replace(/\/\*.*$/, "");
|
|
55
56
|
if (!basePattern || basePattern === entry) {
|
|
56
57
|
basePattern = path.dirname(entry.split("*")[0]);
|
|
57
58
|
}
|
|
58
|
-
log("\u57FA\u7840\u76EE\u5F55\u6A21\u5F0F:", basePattern);
|
|
59
59
|
const candidateFiles = [];
|
|
60
60
|
for (const file of files) {
|
|
61
61
|
if (exclude.includes(file)) {
|
|
62
|
-
log(`\u8DF3\u8FC7\u6392\u9664\u6587\u4EF6: ${file}`);
|
|
63
62
|
continue;
|
|
64
63
|
}
|
|
65
64
|
const relativePath = path.relative(basePattern, file);
|
|
66
65
|
const pathParts = relativePath.split(path.sep);
|
|
67
|
-
log(`\u5904\u7406\u6587\u4EF6: ${file}`);
|
|
68
|
-
log(`\u76F8\u5BF9\u8DEF\u5F84: ${relativePath}`);
|
|
69
|
-
log(`\u8DEF\u5F84\u90E8\u5206: ${pathParts}`);
|
|
70
66
|
if (pathParts.length === 1) {
|
|
71
67
|
const fileName = pathParts[0];
|
|
72
68
|
const name = path.basename(fileName, path.extname(fileName));
|
|
73
69
|
candidateFiles.push({ name, file, priority: 1 });
|
|
74
|
-
log(`\u{1F4C4} \u7B2C\u4E00\u7EA7\u6587\u4EF6: ${file} -> ${name}.html (\u4F18\u5148\u7EA7: 1)`);
|
|
75
70
|
} else if (pathParts.length >= 2) {
|
|
76
71
|
const fileName = path.basename(file, path.extname(file));
|
|
77
72
|
const dirName = pathParts[0];
|
|
78
73
|
if (fileName === "main") {
|
|
79
74
|
candidateFiles.push({ name: dirName, file, priority: 2 });
|
|
80
|
-
log(`\u{1F4C1} \u76EE\u5F55main\u6587\u4EF6: ${file} -> ${dirName}.html (\u4F18\u5148\u7EA7: 2)`);
|
|
81
|
-
} else {
|
|
82
|
-
log(`\u274C \u8DF3\u8FC7\u6587\u4EF6: ${file} (\u4E0D\u662Fmain\u6587\u4EF6)`);
|
|
83
75
|
}
|
|
84
|
-
} else {
|
|
85
|
-
log(`\u274C \u8DF3\u8FC7\u6587\u4EF6: ${file} (\u8DEF\u5F84\u5C42\u7EA7\u4E0D\u7B26\u5408)`);
|
|
86
76
|
}
|
|
87
77
|
}
|
|
88
78
|
for (const candidate of candidateFiles) {
|
|
89
79
|
const existing = nameToFile.get(candidate.name);
|
|
90
80
|
if (!existing) {
|
|
91
81
|
nameToFile.set(candidate.name, { file: candidate.file, priority: candidate.priority });
|
|
92
|
-
log(`\u2705 \u6DFB\u52A0\u9875\u9762: ${candidate.name} -> ${candidate.file}`);
|
|
93
82
|
} else {
|
|
94
83
|
if (candidate.priority > existing.priority) {
|
|
95
84
|
nameToFile.set(candidate.name, { file: candidate.file, priority: candidate.priority });
|
|
96
|
-
log(
|
|
97
|
-
`\u{1F504} \u66FF\u6362\u9875\u9762: ${candidate.name} -> ${candidate.file} (\u66FF\u6362 ${existing.file}, \u76EE\u5F55\u4F18\u5148)`
|
|
98
|
-
);
|
|
99
|
-
} else {
|
|
100
|
-
log(`\u26A0\uFE0F \u51B2\u7A81\u8DF3\u8FC7: ${candidate.name} -> ${candidate.file} (\u4FDD\u7559 ${existing.file})`);
|
|
101
85
|
}
|
|
102
86
|
}
|
|
103
87
|
}
|
|
@@ -126,7 +110,6 @@ function getPageConfig(pageConfigs, context, log) {
|
|
|
126
110
|
if (typeof pageConfigs === "function") {
|
|
127
111
|
const result = pageConfigs(context);
|
|
128
112
|
if (result) {
|
|
129
|
-
log(`\u51FD\u6570\u914D\u7F6E\u5339\u914D\u9875\u9762 ${context.pageName}:`, result);
|
|
130
113
|
}
|
|
131
114
|
return result;
|
|
132
115
|
}
|
|
@@ -434,7 +417,6 @@ function generateBuildConfig(options) {
|
|
|
434
417
|
log("\u8B66\u544A: \u672A\u627E\u5230\u5339\u914D\u7684\u5165\u53E3\u6587\u4EF6");
|
|
435
418
|
return {};
|
|
436
419
|
}
|
|
437
|
-
log(`\u53D1\u73B0 ${entryFiles.length} \u4E2A\u9875\u9762\u5165\u53E3`);
|
|
438
420
|
const pageStrategies = /* @__PURE__ */ new Map();
|
|
439
421
|
const strategyPages = /* @__PURE__ */ new Map();
|
|
440
422
|
for (const entryFile of entryFiles) {
|
|
@@ -451,7 +433,7 @@ function generateBuildConfig(options) {
|
|
|
451
433
|
}
|
|
452
434
|
(_a = strategyPages.get(strategyName)) == null ? void 0 : _a.push(entryFile.name);
|
|
453
435
|
}
|
|
454
|
-
log(
|
|
436
|
+
log(`\u{1F4C4} \u53D1\u73B0 ${entryFiles.length} \u4E2A\u9875\u9762: ${entryFiles.map((f) => f.name).join(", ")}`);
|
|
455
437
|
if (forceBuildStrategy) {
|
|
456
438
|
const targetPages = strategyPages.get(forceBuildStrategy) || [];
|
|
457
439
|
if (targetPages.length === 0) {
|
|
@@ -475,7 +457,6 @@ function generateBuildConfig(options) {
|
|
|
475
457
|
for (const [strategyName, pages] of strategyPages) {
|
|
476
458
|
if (pages.length === 0)
|
|
477
459
|
continue;
|
|
478
|
-
log(`\u751F\u6210\u7B56\u7565 "${strategyName}" \u7684\u6784\u5EFA\u914D\u7F6E, \u9875\u9762: ${pages.join(", ")}`);
|
|
479
460
|
const strategyConfig = strategies[strategyName] || {};
|
|
480
461
|
const config = generateStrategyConfig(
|
|
481
462
|
strategyName,
|
|
@@ -504,7 +485,8 @@ function generateBuildConfig(options) {
|
|
|
504
485
|
);
|
|
505
486
|
buildConfigs["default"] = defaultConfig;
|
|
506
487
|
}
|
|
507
|
-
|
|
488
|
+
const strategyNames = Object.keys(buildConfigs);
|
|
489
|
+
log(`\u{1F4E6} \u6784\u5EFA\u7B56\u7565: ${strategyNames.join(", ")}`);
|
|
508
490
|
return buildConfigs;
|
|
509
491
|
} catch (error) {
|
|
510
492
|
log("\u751F\u6210\u6784\u5EFA\u914D\u7F6E\u5931\u8D25:", error);
|
|
@@ -514,6 +496,7 @@ function generateBuildConfig(options) {
|
|
|
514
496
|
function generateStrategyConfig(strategyName, pages, entryFiles, strategyConfig, pageConfigs, defaultTemplate, placeholder, log) {
|
|
515
497
|
const htmlInputs = {};
|
|
516
498
|
const tempFiles = [];
|
|
499
|
+
const allPageDefines = {};
|
|
517
500
|
for (const pageName of pages) {
|
|
518
501
|
const entryFile = entryFiles.find((f) => f.name === pageName);
|
|
519
502
|
if (!entryFile)
|
|
@@ -525,6 +508,9 @@ function generateStrategyConfig(strategyName, pages, entryFiles, strategyConfig,
|
|
|
525
508
|
strategy: strategyName
|
|
526
509
|
};
|
|
527
510
|
const pageConfig = getPageConfig(pageConfigs, pageContext, log);
|
|
511
|
+
if (pageConfig == null ? void 0 : pageConfig.define) {
|
|
512
|
+
Object.assign(allPageDefines, pageConfig.define);
|
|
513
|
+
}
|
|
528
514
|
let templatePath = defaultTemplate;
|
|
529
515
|
const pageSpecificTemplate = `${pageName}.html`;
|
|
530
516
|
if (fs2.existsSync(path3.resolve(process.cwd(), pageSpecificTemplate))) {
|
|
@@ -545,21 +531,6 @@ function generateStrategyConfig(strategyName, pages, entryFiles, strategyConfig,
|
|
|
545
531
|
entryPath
|
|
546
532
|
);
|
|
547
533
|
}
|
|
548
|
-
if (pageConfig == null ? void 0 : pageConfig.define) {
|
|
549
|
-
const defineScript = Object.entries(pageConfig.define).map(([key, value]) => {
|
|
550
|
-
const stringValue = typeof value === "string" ? `"${value}"` : JSON.stringify(value);
|
|
551
|
-
return `window.${key} = ${stringValue};`;
|
|
552
|
-
}).join("\n");
|
|
553
|
-
if (defineScript) {
|
|
554
|
-
templateContent = templateContent.replace(
|
|
555
|
-
/<\/head>/i,
|
|
556
|
-
`<script type="text/javascript">
|
|
557
|
-
${defineScript}
|
|
558
|
-
</script>
|
|
559
|
-
</head>`
|
|
560
|
-
);
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
534
|
const tempHtmlPath = path3.resolve(process.cwd(), `.temp.mp.${pageName}.html`);
|
|
564
535
|
fs2.writeFileSync(tempHtmlPath, templateContent);
|
|
565
536
|
tempFiles.push(tempHtmlPath);
|
|
@@ -587,6 +558,12 @@ ${defineScript}
|
|
|
587
558
|
if (strategyConfig) {
|
|
588
559
|
config = (0, import_vite.mergeConfig)(baseConfig, strategyConfig);
|
|
589
560
|
}
|
|
561
|
+
if (Object.keys(allPageDefines).length > 0) {
|
|
562
|
+
config.define = {
|
|
563
|
+
...config.define,
|
|
564
|
+
...allPageDefines
|
|
565
|
+
};
|
|
566
|
+
}
|
|
590
567
|
if (!config.build)
|
|
591
568
|
config.build = {};
|
|
592
569
|
if (!config.build.rollupOptions)
|
|
@@ -643,7 +620,11 @@ function hasCustomConfig() {
|
|
|
643
620
|
async function loadUserConfig(context) {
|
|
644
621
|
const customConfig = await loadCustomConfig();
|
|
645
622
|
if (customConfig) {
|
|
646
|
-
|
|
623
|
+
const result = customConfig(context);
|
|
624
|
+
if (!result) {
|
|
625
|
+
return {};
|
|
626
|
+
}
|
|
627
|
+
return result;
|
|
647
628
|
}
|
|
648
629
|
return null;
|
|
649
630
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/dev-server.ts","../src/file-filter.ts","../src/utils.ts","../src/page-config.ts","../src/build-config.ts","../src/config-loader.ts","../src/defaults.ts","../src/types.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport type { Plugin } from 'vite';\nimport { mergeConfig } from 'vite';\nimport { setupDevMiddleware } from './dev-server';\nimport { generateBuildConfig } from './build-config';\nimport { loadUserConfig, hasCustomConfig } from './config-loader';\nimport { mergeWithDefaults } from './defaults';\nimport type { Options, ConfigTransformFunction } from './types';\n\n// 导出类型和工具函数\nexport { defineConfig, defineConfigTransform } from './types';\nexport type {\n ConfigFunction,\n ConfigTransformFunction,\n PluginContext,\n PageContext,\n PageConfig,\n} from './types';\n\nexport function viteMultiPage(transform?: ConfigTransformFunction): Plugin {\n let resolvedOptions: Options;\n const tempFiles: string[] = [];\n let log: (...args: any[]) => void = () => {}; // 默认为空函数\n\n return {\n name: 'vite-multi-page',\n\n async configResolved(config) {\n // 加载用户配置文件(如果存在)\n let userConfig: Options | null = null;\n\n if (hasCustomConfig()) {\n userConfig = await loadUserConfig({\n mode: config.command === 'serve' ? 'development' : 'production',\n command: config.command,\n isCLI: false,\n });\n }\n\n // 合并用户配置和默认配置\n const mergedConfig = mergeWithDefaults(userConfig);\n\n // 应用配置变换函数(如果提供)\n resolvedOptions = transform\n ? transform(mergedConfig, {\n mode: config.command === 'serve' ? 'development' : 'production',\n command: config.command,\n isCLI: false,\n })\n : mergedConfig;\n\n // 设置debug日志\n const debug = resolvedOptions.debug ?? false;\n log = debug ? console.log.bind(console, '[vite-multi-page]') : () => {};\n\n log('Vite配置已解析, 使用配置:', {\n strategies: Object.keys(resolvedOptions.strategies || {}),\n entry: resolvedOptions.entry,\n });\n },\n\n async config(config, { command }) {\n if (command === 'build') {\n // 在config钩子中临时加载配置,因为configResolved还没运行\n if (!resolvedOptions) {\n // 加载用户配置文件(如果存在)\n let userConfig: Options | null = null;\n\n if (hasCustomConfig()) {\n userConfig = await loadUserConfig({\n mode: 'production',\n command: 'build',\n isCLI: false,\n });\n }\n\n // 合并用户配置和默认配置\n const mergedConfig = mergeWithDefaults(userConfig);\n\n // 应用配置变换函数(如果提供)\n resolvedOptions = transform\n ? transform(mergedConfig, {\n mode: 'production',\n command: 'build',\n isCLI: false,\n })\n : mergedConfig;\n const debug = resolvedOptions.debug ?? false;\n log = debug ? console.log.bind(console, '[vite-multi-page]') : () => {};\n }\n\n log('配置构建模式');\n\n // 生成构建配置\n const forceBuildStrategy = process.env.VITE_BUILD_STRATEGY;\n const buildConfigs = generateBuildConfig({\n entry: resolvedOptions.entry || 'src/pages/**/*.{ts,js}',\n exclude: resolvedOptions.exclude || [],\n template: resolvedOptions.template || 'index.html',\n placeholder: resolvedOptions.placeholder || '{{ENTRY_FILE}}',\n strategies: resolvedOptions.strategies || {},\n pageConfigs: resolvedOptions.pageConfigs || {},\n forceBuildStrategy,\n });\n\n // 应用构建配置中的策略(如果有forceBuildStrategy,buildConfigs只会包含该策略)\n const targetStrategy = Object.keys(buildConfigs)[0];\n\n if (targetStrategy && buildConfigs[targetStrategy]) {\n log(`应用构建策略: ${targetStrategy}`);\n const strategyConfig = buildConfigs[targetStrategy];\n\n // 使用Vite的mergeConfig进行智能深度合并\n const mergedConfig = mergeConfig(config, strategyConfig);\n\n // 将合并结果复制回config对象\n Object.assign(config, mergedConfig);\n\n log(`已应用策略 \"${targetStrategy}\" 的配置:`, {\n build: !!strategyConfig.build,\n define: !!strategyConfig.define,\n plugins: strategyConfig.plugins?.length || 0,\n });\n } else {\n log('未找到可用的构建策略,使用默认配置');\n\n throw new Error(\n '❌ 构建失败: 未找到任何构建策略\\n\\n' +\n '可能的原因:\\n' +\n ' 1. 配置文件返回空对象 {}\\n' +\n ' 2. 未找到匹配的入口文件\\n' +\n ' 3. 模板文件不存在\\n' +\n ' 4. 未配置 strategies 对象\\n\\n' +\n '最小配置示例:\\n' +\n 'export default () => ({\\n' +\n ' entry: \"src/pages/**/*.{ts,js}\",\\n' +\n ' template: \"index.html\",\\n' +\n ' strategies: {\\n' +\n ' default: {}\\n' +\n ' }\\n' +\n '});'\n );\n }\n }\n },\n\n configureServer(server) {\n if (server.config.command === 'serve') {\n log('配置开发服务器');\n\n setupDevMiddleware(\n server,\n {\n entry: resolvedOptions.entry || 'src/pages/**/*.{ts,js}',\n exclude: resolvedOptions.exclude || [],\n template: resolvedOptions.template || 'index.html',\n placeholder: resolvedOptions.placeholder || '{{ENTRY_FILE}}',\n strategies: resolvedOptions.strategies || {},\n pageConfigs: resolvedOptions.pageConfigs || {},\n },\n log\n );\n }\n },\n\n buildEnd() {\n // 清理临时文件\n if (tempFiles.length > 0) {\n log(`清理 ${tempFiles.length} 个临时文件`);\n tempFiles.forEach(file => {\n try {\n if (fs.existsSync(file)) {\n fs.unlinkSync(file);\n log(`删除临时文件: ${file}`);\n }\n } catch (error) {\n log(`删除临时文件失败: ${file}`, error);\n }\n });\n tempFiles.length = 0;\n }\n },\n };\n}\n\nexport default viteMultiPage;\nexport type { Options } from './types';\nexport { generateBuildConfig, getAvailableStrategies } from './build-config';\n","import type { ViteDevServer } from 'vite';\nimport * as path from 'node:path';\nimport * as fs from 'node:fs';\nimport { glob } from 'glob';\nimport { filterEntryFiles } from './file-filter';\nimport { escapeRegExp } from './utils';\nimport { DevServerOptions, PageConfigContext } from './types';\nimport { getPageConfig } from './page-config';\n\nexport function configureDevServer(\n server: ViteDevServer,\n options: DevServerOptions,\n log: (...args: any[]) => void\n) {\n try {\n const allFiles = glob.sync(options.entry, { cwd: process.cwd() });\n let entryFiles = filterEntryFiles(allFiles, options.entry, options.exclude, log);\n\n if (entryFiles.length === 0) {\n log('警告: 未找到匹配的入口文件');\n return;\n }\n\n // 获取指定的策略,优先使用命令行参数\n const cliStrategy = ((server.config as any).__cliStrategy ||\n (server.config as any).strategy) as string | undefined;\n\n // 如果指定了策略,则只显示该策略下的页面或没有指定策略的默认页面\n if (cliStrategy) {\n log(`开发服务器使用指定的策略: ${cliStrategy}`);\n\n // 过滤入口文件,只保留匹配策略的页面\n entryFiles = entryFiles.filter(file => {\n const pageName = file.name;\n const pageStrategy = options.appliedStrategies?.get(pageName) || undefined;\n\n // 在指定策略为default时,包含所有没有指定策略的页面\n if (cliStrategy === 'default') {\n return !pageStrategy || pageStrategy === 'default';\n }\n\n // 其他策略,只包含匹配的页面\n return pageStrategy === cliStrategy;\n });\n\n log(`策略 \"${cliStrategy}\" 下可用的页面: ${entryFiles.map(f => f.name).join(', ') || '无'}`);\n }\n\n log('开发服务器应用的入口文件:', entryFiles);\n\n // 修改中间件来处理HTML请求\n server.middlewares.use(async (req, res, next) => {\n try {\n const url = req.url || '';\n const pathWithoutQuery = url.split('?')[0];\n\n // 处理根路径请求 - 显示所有页面的索引\n if (pathWithoutQuery === '/') {\n const indexHtml = generateIndexHtml(entryFiles, options, log);\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/html');\n res.end(indexHtml);\n return;\n }\n\n // 跳过明显的静态资源请求\n if (\n pathWithoutQuery.match(/\\.(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)$/) &&\n !pathWithoutQuery.endsWith('.html')\n ) {\n return next();\n }\n\n // 提取页面名称,同时处理带.html后缀和不带后缀的情况\n let pageName = '';\n if (pathWithoutQuery.endsWith('.html')) {\n pageName = path.basename(pathWithoutQuery, '.html');\n } else if (pathWithoutQuery.startsWith('/')) {\n // 处理无扩展名的路径,如 /mobile\n pageName = pathWithoutQuery.substring(1); // 移除开头的斜杠\n }\n\n if (!pageName) {\n return next();\n }\n\n const matchedFile = entryFiles.find(file => file.name === pageName);\n\n if (!matchedFile) {\n return next();\n }\n\n // 获取页面配置\n const pageContext = {\n pageName: matchedFile.name,\n filePath: matchedFile.file,\n relativePath: path.relative(process.cwd(), matchedFile.file),\n strategy: undefined,\n isMatched: false,\n } as PageConfigContext;\n\n const pageConfig = getPageConfig(options.pageConfigs, pageContext, log);\n\n // 应用配置策略\n if (pageConfig?.strategy) {\n pageContext.strategy = pageConfig.strategy;\n } else if (options.appliedStrategies?.has(pageName)) {\n // 使用缓存的策略信息\n const strategyName = options.appliedStrategies.get(pageName);\n if (strategyName) {\n pageContext.strategy = strategyName;\n }\n }\n\n // 获取模板文件路径\n // 首先检查是否有页面特定的模板(例如mobile.html对应mobile页面)\n let templatePath = '';\n\n // 尝试以页面名称查找匹配的模板\n const pageSpecificTemplate = path.resolve(process.cwd(), `${pageName}.html`);\n if (fs.existsSync(pageSpecificTemplate)) {\n templatePath = pageSpecificTemplate;\n }\n // 然后尝试使用页面配置中指定的模板\n else if (pageConfig?.template) {\n templatePath = path.resolve(process.cwd(), pageConfig.template);\n }\n // 最后使用默认模板\n else {\n templatePath = path.resolve(process.cwd(), options.template);\n }\n\n if (!fs.existsSync(templatePath)) {\n return next();\n }\n\n // 读取并修改模板\n let html = fs.readFileSync(templatePath, 'utf-8');\n\n // 检查模板中是否包含占位符\n const containsPlaceholder = html.includes(options.placeholder);\n\n // 替换占位符为入口文件路径\n if (containsPlaceholder) {\n const originalHtml = html;\n\n // 方式1: 直接字符串替换\n html = html.split(options.placeholder).join(`/${matchedFile.file}`);\n\n // 检查替换结果\n if (html === originalHtml) {\n // 方式2: 正则表达式替换\n const escapedPlaceholder = escapeRegExp(options.placeholder);\n const placeholderRegex = new RegExp(escapedPlaceholder, 'g');\n html = originalHtml.replace(placeholderRegex, `/${matchedFile.file}`);\n\n // 检查替换结果\n if (html === originalHtml) {\n // 方式3: 硬编码替换具体的占位符格式\n html = originalHtml.replace(/\\{\\{ENTRY_FILE\\}\\}/g, `/${matchedFile.file}`);\n }\n }\n }\n\n // 添加页面级define变量\n if (pageConfig?.define) {\n const defineScript = Object.entries(pageConfig.define)\n .map(([key, value]) => {\n const stringValue = typeof value === 'string' ? `\"${value}\"` : JSON.stringify(value);\n return `window.${key} = ${stringValue};`;\n })\n .join('\\n');\n\n if (defineScript) {\n // 注入到head标签底部\n html = html.replace(\n /<\\/head>/i,\n `<script type=\"text/javascript\">\\n${defineScript}\\n</script>\\n</head>`\n );\n }\n }\n\n // 发送响应\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/html');\n res.end(html);\n } catch (error) {\n log(`开发服务器处理请求失败: ${error}`);\n next(error);\n }\n });\n\n log('开发服务器配置完成');\n } catch (error) {\n log(`配置开发服务器失败: ${error}`);\n throw error;\n }\n}\n\n// 为了兼容性,导出setupDevMiddleware作为configureDevServer的别名\nexport const setupDevMiddleware = configureDevServer;\n\n// 生成索引页面HTML\nfunction generateIndexHtml(\n entryFiles: { name: string; file: string }[],\n options: DevServerOptions,\n log: (...args: any[]) => void\n): string {\n try {\n const pageItems = entryFiles\n .map(file => {\n // 获取页面配置和策略\n const pageContext = {\n pageName: file.name,\n filePath: file.file,\n relativePath: path.relative(process.cwd(), file.file),\n strategy: undefined,\n isMatched: false,\n };\n\n const pageConfig = getPageConfig(options.pageConfigs, pageContext, log);\n\n // 确定策略\n let strategy = 'default';\n if (pageConfig?.strategy) {\n strategy = pageConfig.strategy;\n } else if (options.appliedStrategies?.has(file.name)) {\n const strategyName = options.appliedStrategies.get(file.name);\n if (strategyName) {\n strategy = strategyName;\n }\n }\n\n const strategyBadge =\n strategy !== 'default' ? `<span class=\"badge\">${strategy}</span>` : '';\n\n return `\n <div class=\"page-item\">\n <a href=\"${file.name}.html\" class=\"page-link\">\n ${file.name}${strategyBadge}\n </a>\n <div class=\"page-path\">${file.file}</div>\n </div>`;\n })\n .join('');\n\n return `\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>多页面应用索引</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;\n line-height: 1.6;\n color: #333;\n max-width: 1200px;\n margin: 0 auto;\n padding: 20px;\n background-color: #f5f5f7;\n }\n h1 {\n font-size: 24px;\n margin-bottom: 20px;\n color: #111;\n }\n .page-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n }\n .page-item {\n background-color: white;\n border-radius: 8px;\n padding: 16px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.1);\n transition: transform 0.2s, box-shadow 0.2s;\n }\n .page-item:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 8px rgba(0,0,0,0.1);\n }\n .page-link {\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 18px;\n font-weight: 500;\n color: #0066cc;\n text-decoration: none;\n margin-bottom: 8px;\n }\n .page-path {\n font-size: 14px;\n color: #666;\n word-break: break-all;\n }\n .badge {\n display: inline-block;\n font-size: 12px;\n padding: 2px 8px;\n border-radius: 12px;\n background-color: #e6f2ff;\n color: #0066cc;\n margin-left: 8px;\n }\n .stats {\n margin-bottom: 20px;\n font-size: 14px;\n color: #666;\n }\n </style>\n </head>\n <body>\n <h1>多页面应用索引</h1>\n <div class=\"stats\">\n 找到 ${entryFiles.length} 个页面\n </div>\n <div class=\"page-list\">\n ${pageItems}\n </div>\n </body>\n </html>\n `;\n } catch (error) {\n log(`生成索引页失败: ${error}`);\n return `\n <!DOCTYPE html>\n <html>\n <head>\n <title>错误</title>\n </head>\n <body>\n <h1>生成索引页时发生错误</h1>\n <p>${error}</p>\n </body>\n </html>\n `;\n }\n}\n","import * as path from 'node:path';\nimport type { EntryFile, CandidateFile } from './types';\n\nexport function filterEntryFiles(\n files: string[],\n entry: string,\n exclude: string[],\n log: (...args: any[]) => void\n): EntryFile[] {\n const result: EntryFile[] = [];\n const nameToFile = new Map<string, { file: string; priority: number }>();\n\n // 从entry模式中提取基础目录\n let basePattern = entry.replace(/\\/\\*.*$/, ''); // 去掉glob部分\n // 如果基础模式为空或不合理,使用默认处理\n if (!basePattern || basePattern === entry) {\n basePattern = path.dirname(entry.split('*')[0]);\n }\n log('基础目录模式:', basePattern);\n\n const candidateFiles: CandidateFile[] = [];\n\n for (const file of files) {\n if (exclude.includes(file)) {\n log(`跳过排除文件: ${file}`);\n continue;\n }\n\n const relativePath = path.relative(basePattern, file);\n const pathParts = relativePath.split(path.sep);\n\n log(`处理文件: ${file}`);\n log(`相对路径: ${relativePath}`);\n log(`路径部分: ${pathParts}`);\n\n if (pathParts.length === 1) {\n // 第一级文件:src/pages/about.js -> /about.html\n const fileName = pathParts[0];\n const name = path.basename(fileName, path.extname(fileName));\n candidateFiles.push({ name, file, priority: 1 });\n log(`📄 第一级文件: ${file} -> ${name}.html (优先级: 1)`);\n } else if (pathParts.length >= 2) {\n // 目录下的文件\n const fileName = path.basename(file, path.extname(file));\n const dirName = pathParts[0];\n\n if (fileName === 'main') {\n // 目录下的main文件:src/pages/mobile/main.ts -> /mobile.html\n candidateFiles.push({ name: dirName, file, priority: 2 });\n log(`📁 目录main文件: ${file} -> ${dirName}.html (优先级: 2)`);\n } else {\n log(`❌ 跳过文件: ${file} (不是main文件)`);\n }\n } else {\n log(`❌ 跳过文件: ${file} (路径层级不符合)`);\n }\n }\n\n // 按照优先级处理冲突:目录优先覆盖文件(优先级2 > 优先级1)\n for (const candidate of candidateFiles) {\n const existing = nameToFile.get(candidate.name);\n\n if (!existing) {\n nameToFile.set(candidate.name, { file: candidate.file, priority: candidate.priority });\n log(`✅ 添加页面: ${candidate.name} -> ${candidate.file}`);\n } else {\n if (candidate.priority > existing.priority) {\n nameToFile.set(candidate.name, { file: candidate.file, priority: candidate.priority });\n log(\n `🔄 替换页面: ${candidate.name} -> ${candidate.file} (替换 ${existing.file}, 目录优先)`\n );\n } else {\n log(`⚠️ 冲突跳过: ${candidate.name} -> ${candidate.file} (保留 ${existing.file})`);\n }\n }\n }\n\n for (const [name, { file }] of nameToFile.entries()) {\n result.push({ name, file });\n }\n\n return result;\n}\n","export function escapeRegExp(string: string): string {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function createLogger(debug: boolean) {\n return (...args: any[]) => {\n if (debug) {\n console.log('[vite-plugin-multi-page]', ...args);\n }\n };\n}\n","import type { PageConfig, PageConfigFunction, PageConfigContext } from './types';\n\n/**\n * 根据页面上下文获取页面配置\n */\nexport function getPageConfig(\n pageConfigs: Record<string, PageConfig> | PageConfigFunction | undefined,\n context: PageConfigContext,\n log: (...args: any[]) => void\n): PageConfig | null {\n if (!pageConfigs) return null;\n\n // 如果是函数,直接调用\n if (typeof pageConfigs === 'function') {\n const result = pageConfigs(context);\n if (result) {\n log(`函数配置匹配页面 ${context.pageName}:`, result);\n }\n return result;\n }\n\n // 对象配置:支持精确匹配和模式匹配\n for (const [key, config] of Object.entries(pageConfigs)) {\n // 精确匹配页面名称\n if (key === context.pageName) {\n log(`精确匹配页面 ${context.pageName}:`, config);\n return config;\n }\n\n // 模式匹配\n if (config.match) {\n const patterns = Array.isArray(config.match) ? config.match : [config.match];\n const isMatched = patterns.some(\n pattern =>\n simpleMatch(pattern, context.pageName) ||\n simpleMatch(pattern, context.relativePath) ||\n simpleMatch(pattern, context.filePath)\n );\n\n if (isMatched) {\n log(`模式匹配页面 ${context.pageName} (模式: ${config.match}):`, config);\n return { ...config, match: undefined };\n }\n }\n\n // glob 模式匹配页面名称\n if (simpleMatch(key, context.pageName)) {\n log(`Glob匹配页面 ${context.pageName} (模式: ${key}):`, config);\n return config;\n }\n }\n\n return null;\n}\n\n/**\n * 简单的模式匹配函数\n */\nfunction simpleMatch(pattern: string, text: string): boolean {\n const regexPattern = pattern\n .replace(/\\*\\*/g, '__DOUBLE_STAR__')\n .replace(/\\*/g, '[^/]*')\n .replace(/__DOUBLE_STAR__/g, '.*');\n const regex = new RegExp(`^${regexPattern}$`);\n return regex.test(text);\n}\n","import type { UserConfig } from 'vite';\nimport { mergeConfig } from 'vite';\nimport { glob } from 'glob';\nimport * as path from 'node:path';\nimport * as fs from 'node:fs';\nimport { filterEntryFiles } from './file-filter';\nimport { getPageConfig } from './page-config';\nimport type { BuildConfigOptions, PageConfigContext, ConfigStrategy } from './types';\nimport { createLogger } from './utils';\n\n/**\n * 构建时配置生成器\n * 根据策略和页面配置生成多页面构建配置\n */\nexport function generateBuildConfig(options: BuildConfigOptions): Record<string, UserConfig> {\n const {\n entry = 'src/pages/*/main.{ts,js}',\n exclude = [],\n template = 'index.html',\n placeholder = '<!--VITE_MULTI_PAGE_ENTRY-->',\n strategies = {},\n pageConfigs = {},\n forceBuildStrategy,\n } = options;\n\n const log = createLogger(true);\n const buildConfigs: Record<string, UserConfig> = {};\n\n try {\n // 1. 发现所有页面入口文件\n const allFiles = glob.sync(entry, { cwd: process.cwd() });\n const entryFiles = filterEntryFiles(allFiles, entry, exclude, log);\n\n if (entryFiles.length === 0) {\n log('警告: 未找到匹配的入口文件');\n return {};\n }\n\n log(`发现 ${entryFiles.length} 个页面入口`);\n\n // 2. 为每个页面分析配置和策略\n const pageStrategies = new Map<string, string>();\n const strategyPages = new Map<string, string[]>();\n\n for (const entryFile of entryFiles) {\n const pageContext = {\n pageName: entryFile.name,\n filePath: entryFile.file,\n relativePath: path.relative(process.cwd(), entryFile.file),\n } as PageConfigContext;\n\n // 获取页面配置\n const pageConfig = getPageConfig(pageConfigs, pageContext, log);\n const strategyName = pageConfig?.strategy || 'default';\n\n pageStrategies.set(entryFile.name, strategyName);\n\n if (!strategyPages.has(strategyName)) {\n strategyPages.set(strategyName, []);\n }\n strategyPages.get(strategyName)?.push(entryFile.name);\n }\n\n log('页面策略分布:', Object.fromEntries(pageStrategies));\n\n // 3. 如果指定了强制策略,只构建该策略的页面\n if (forceBuildStrategy) {\n const targetPages = strategyPages.get(forceBuildStrategy) || [];\n if (targetPages.length === 0) {\n log(`警告: 策略 \"${forceBuildStrategy}\" 下没有页面`);\n return {};\n }\n\n log(`强制构建策略: ${forceBuildStrategy}, 页面: ${targetPages.join(', ')}`);\n\n const config = generateStrategyConfig(\n forceBuildStrategy,\n targetPages,\n entryFiles,\n strategies[forceBuildStrategy],\n pageConfigs,\n template,\n placeholder,\n log\n );\n\n buildConfigs[forceBuildStrategy] = config;\n return buildConfigs;\n }\n\n // 4. 为每个策略生成构建配置\n for (const [strategyName, pages] of strategyPages) {\n if (pages.length === 0) continue;\n\n log(`生成策略 \"${strategyName}\" 的构建配置, 页面: ${pages.join(', ')}`);\n\n // 获取策略配置,如果没有定义则使用空配置(允许默认策略)\n const strategyConfig = strategies[strategyName] || {};\n const config = generateStrategyConfig(\n strategyName,\n pages,\n entryFiles,\n strategyConfig,\n pageConfigs,\n template,\n placeholder,\n log\n );\n\n buildConfigs[strategyName] = config;\n }\n\n // 确保至少有一个构建配置\n if (Object.keys(buildConfigs).length === 0) {\n log('警告: 未生成任何构建配置,创建默认配置');\n\n // 如果没有任何策略,创建一个默认策略包含所有页面\n const allPageNames = entryFiles.map(f => f.name);\n const defaultConfig = generateStrategyConfig(\n 'default',\n allPageNames,\n entryFiles,\n {},\n pageConfigs,\n template,\n placeholder,\n log\n );\n\n buildConfigs['default'] = defaultConfig;\n }\n\n log(`生成了 ${Object.keys(buildConfigs).length} 个构建配置`);\n return buildConfigs;\n } catch (error) {\n log('生成构建配置失败:', error);\n throw error;\n }\n}\n\n/**\n * 为特定策略生成构建配置\n */\nfunction generateStrategyConfig(\n strategyName: string,\n pages: string[],\n entryFiles: Array<{ name: string; file: string }>,\n strategyConfig: ConfigStrategy | undefined,\n pageConfigs: any,\n defaultTemplate: string,\n placeholder: string,\n log: (...args: any[]) => void\n): UserConfig {\n const htmlInputs: Record<string, string> = {};\n const tempFiles: string[] = [];\n\n // 为每个页面确定使用的HTML模板并创建临时文件\n for (const pageName of pages) {\n const entryFile = entryFiles.find(f => f.name === pageName);\n if (!entryFile) continue;\n\n // 获取页面配置\n const pageContext = {\n pageName,\n filePath: entryFile.file,\n relativePath: path.relative(process.cwd(), entryFile.file),\n strategy: strategyName,\n } as PageConfigContext;\n\n const pageConfig = getPageConfig(pageConfigs, pageContext, log);\n\n // 确定HTML模板\n let templatePath = defaultTemplate;\n\n // 1. 页面特定模板(如 mobile.html 对应 mobile 页面)\n const pageSpecificTemplate = `${pageName}.html`;\n if (fs.existsSync(path.resolve(process.cwd(), pageSpecificTemplate))) {\n templatePath = pageSpecificTemplate;\n }\n // 2. 页面配置中指定的模板\n else if (pageConfig?.template) {\n templatePath = pageConfig.template;\n }\n\n // 读取模板内容\n const templateFullPath = path.resolve(process.cwd(), templatePath);\n if (!fs.existsSync(templateFullPath)) {\n log(`警告: 模板文件不存在: ${templatePath}`);\n continue;\n }\n\n let templateContent = fs.readFileSync(templateFullPath, 'utf-8');\n\n // 替换占位符\n if (templateContent.includes(placeholder)) {\n // 临时HTML在项目根目录中,使用相对路径\n const entryPath = `./${entryFile.file}`;\n templateContent = templateContent.replace(\n new RegExp(placeholder.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'g'),\n entryPath\n );\n }\n\n // 添加页面级define变量\n if (pageConfig?.define) {\n const defineScript = Object.entries(pageConfig.define)\n .map(([key, value]) => {\n const stringValue = typeof value === 'string' ? `\"${value}\"` : JSON.stringify(value);\n return `window.${key} = ${stringValue};`;\n })\n .join('\\n');\n\n if (defineScript) {\n templateContent = templateContent.replace(\n /<\\/head>/i,\n `<script type=\"text/javascript\">\\n${defineScript}\\n</script>\\n</head>`\n );\n }\n }\n\n // 创建临时HTML文件,使用新的命名规则:.temp.mp.[name].html\n const tempHtmlPath = path.resolve(process.cwd(), `.temp.mp.${pageName}.html`);\n fs.writeFileSync(tempHtmlPath, templateContent);\n tempFiles.push(tempHtmlPath);\n\n htmlInputs[pageName] = tempHtmlPath;\n }\n\n // 构建基础配置\n const baseConfig: UserConfig = {\n build: {\n rollupOptions: {\n input: htmlInputs, // 使用临时HTML文件作为输入\n output: {\n entryFileNames: 'assets/[name]-[hash].js',\n chunkFileNames: 'assets/[name]-[hash].js',\n assetFileNames: 'assets/[name]-[hash][extname]',\n },\n },\n outDir: `dist/${strategyName}`, // 直接输出到策略目录\n emptyOutDir: false, // 不清空输出目录,避免删除临时HTML文件\n },\n define: {},\n };\n\n // 使用Vite的mergeConfig进行智能深度合并\n let config: UserConfig = baseConfig;\n\n if (strategyConfig) {\n config = mergeConfig(baseConfig, strategyConfig);\n }\n\n // 手动处理需要特殊控制的配置项,防止被mergeConfig覆盖\n if (!config.build) config.build = {};\n if (!config.build.rollupOptions) config.build.rollupOptions = {};\n\n // 确保关键配置不被覆盖\n config.build.outDir = `dist/${strategyName}`; // 强制设置正确的输出目录\n config.build.rollupOptions.input = htmlInputs; // 强制使用临时HTML文件作为输入\n config.build.emptyOutDir = false; // 不清空输出目录,避免删除临时HTML文件\n\n // 简化日志输出\n log(`策略 \"${strategyName}\" - ${pages.length} 个页面`);\n\n return config;\n}\n\n/**\n * 获取所有可用的构建策略\n */\nexport function getAvailableStrategies(options: BuildConfigOptions): string[] {\n const { entry = 'src/pages/*/main.{ts,js}', exclude = [], pageConfigs = {} } = options;\n\n const log = createLogger(false); // 静默模式\n const strategySet = new Set<string>();\n\n try {\n // 发现所有页面入口文件\n const allFiles = glob.sync(entry, { cwd: process.cwd() });\n const entryFiles = filterEntryFiles(allFiles, entry, exclude, log);\n\n // 分析每个页面的策略\n for (const entryFile of entryFiles) {\n const pageContext = {\n pageName: entryFile.name,\n filePath: entryFile.file,\n relativePath: path.relative(process.cwd(), entryFile.file),\n } as PageConfigContext;\n\n const pageConfig = getPageConfig(pageConfigs, pageContext, log);\n const strategyName = pageConfig?.strategy || 'default';\n strategySet.add(strategyName);\n }\n\n // 只返回实际有页面的策略,不添加空策略\n return Array.from(strategySet).sort();\n } catch (error) {\n log('获取可用策略失败:', error);\n return ['default'];\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { Module } from 'node:module';\nimport type { Options } from './types';\n\n/**\n * 配置上下文\n */\nexport interface ConfigContext {\n mode: 'development' | 'production';\n command: 'serve' | 'build';\n isCLI?: boolean;\n}\n\n/**\n * 配置函数类型\n */\nexport type ConfigFunction = (context: ConfigContext) => Options;\n\n/**\n * 配置文件名列表(优先级从高到低)\n */\nconst CONFIG_FILES = [\n 'multipage.config.js',\n 'multipage.config.mjs',\n 'multipage.config.ts',\n] as const;\n\n/**\n * 检查是否存在自定义配置文件\n */\nexport function hasCustomConfig(): boolean {\n for (const filename of CONFIG_FILES) {\n const configPath = path.resolve(process.cwd(), filename);\n if (fs.existsSync(configPath)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * 加载用户的多页面配置\n */\nexport async function loadUserConfig(context: ConfigContext): Promise<Options | null> {\n // 尝试加载项目自定义配置\n const customConfig = await loadCustomConfig();\n\n if (customConfig) {\n // 使用项目自定义配置\n return customConfig(context);\n }\n\n // 没有找到用户配置\n return null;\n}\n\n/**\n * 加载配置文件\n */\nasync function loadConfigFile(filePath: string): Promise<any> {\n // 处理 TypeScript 文件\n if (filePath.endsWith('.ts')) {\n try {\n const code = await fs.promises.readFile(filePath, 'utf-8');\n\n // 使用 esbuild 实时转译 TS → JS\n const esbuild = (await import('esbuild')) as any;\n const result = await esbuild.transform(code, {\n loader: 'ts',\n format: 'cjs', // 使用 CommonJS 格式便于使用 Module._compile\n target: 'node16',\n sourcemap: false,\n });\n\n // 创建临时模块并编译\n const tempModule = new Module(filePath);\n tempModule.filename = filePath;\n tempModule.paths = (Module as any)._nodeModulePaths(path.dirname(filePath));\n\n // 编译代码\n (tempModule as any)._compile(result.code, filePath);\n\n return tempModule.exports;\n } catch (esbuildError) {\n console.warn('esbuild 转译失败,尝试简单转换:', esbuildError);\n\n // 备选方案:简单的文本替换\n const code = await fs.promises.readFile(filePath, 'utf-8');\n const jsCode = code\n .replace(/export\\s+default\\s+/, 'module.exports = ')\n .replace(/import\\s+.*?from\\s+['\"][^'\"]*['\"];?\\s*/g, '')\n .replace(/:\\s*[^=,})\\]]+/g, ''); // 简单的类型注解移除\n\n const tempModule = new Module(filePath);\n tempModule.filename = filePath;\n tempModule.paths = (Module as any)._nodeModulePaths(path.dirname(filePath));\n\n (tempModule as any)._compile(jsCode, filePath);\n return tempModule.exports;\n }\n }\n\n // 处理 JavaScript 文件\n if (filePath.endsWith('.js') || filePath.endsWith('.mjs')) {\n const fileUrl = pathToFileURL(filePath).href;\n return import(`${fileUrl}?t=${Date.now()}`);\n }\n\n throw new Error(`不支持的配置文件类型: ${filePath}`);\n}\n\n/**\n * 加载项目自定义配置文件\n */\nasync function loadCustomConfig(): Promise<ConfigFunction | null> {\n const cwd = process.cwd();\n\n for (const configFile of CONFIG_FILES) {\n const configPath = path.resolve(cwd, configFile);\n\n if (fs.existsSync(configPath)) {\n try {\n const configModule = await loadConfigFile(configPath);\n const configFunction = configModule.default || configModule;\n\n if (typeof configFunction === 'function') {\n return configFunction;\n } else {\n console.warn(`配置文件 ${configFile} 必须默认导出一个函数`);\n }\n } catch (error) {\n if (configFile.endsWith('.ts')) {\n console.error(`加载TypeScript配置文件 ${configFile} 失败:`, error);\n console.log('提示:确保你的项目支持TypeScript,或者使用 .js/.mjs 配置文件');\n } else {\n console.error(`加载配置文件 ${configFile} 失败:`, error);\n }\n }\n }\n }\n\n return null;\n}\n","import type { MultiPageOptions } from './types';\n\n/**\n * 默认配置选项\n */\nexport const DEFAULT_CONFIG: Required<Omit<MultiPageOptions, '__forceBuildStrategy'>> = {\n entry: 'src/pages/**/*.{ts,js}',\n exclude: [],\n template: 'index.html',\n placeholder: '{{ENTRY_FILE}}',\n debug: false,\n strategies: {\n default: {},\n },\n pageConfigs: {},\n};\n\n/**\n * 合并用户配置和默认配置\n */\nexport function mergeWithDefaults(userConfig: MultiPageOptions | null): MultiPageOptions {\n if (!userConfig) {\n return { ...DEFAULT_CONFIG };\n }\n\n return {\n entry: userConfig.entry ?? DEFAULT_CONFIG.entry,\n exclude: userConfig.exclude ?? DEFAULT_CONFIG.exclude,\n template: userConfig.template ?? DEFAULT_CONFIG.template,\n placeholder: userConfig.placeholder ?? DEFAULT_CONFIG.placeholder,\n debug: userConfig.debug ?? DEFAULT_CONFIG.debug,\n strategies: userConfig.strategies ?? DEFAULT_CONFIG.strategies,\n pageConfigs: userConfig.pageConfigs ?? DEFAULT_CONFIG.pageConfigs,\n __forceBuildStrategy: userConfig.__forceBuildStrategy,\n };\n}\n\n/**\n * 检查配置是否为空或无效\n */\nexport function isEmptyConfig(config: MultiPageOptions): boolean {\n // 检查是否是完全空的对象\n if (Object.keys(config).length === 0) {\n return true;\n }\n\n // 检查是否只有默认值或无效值\n const hasValidEntry = config.entry && config.entry !== DEFAULT_CONFIG.entry;\n const hasValidStrategies = config.strategies && Object.keys(config.strategies).length > 0;\n const hasValidPageConfigs =\n config.pageConfigs &&\n (typeof config.pageConfigs === 'function' || Object.keys(config.pageConfigs).length > 0);\n\n return !hasValidEntry && !hasValidStrategies && !hasValidPageConfigs;\n}\n","import type { UserConfig } from 'vite';\n\n// 核心配置选项\nexport interface MultiPageOptions {\n entry?: string;\n exclude?: string[];\n template?: string;\n placeholder?: string;\n debug?: boolean;\n strategies?: Record<string, ConfigStrategy>;\n pageConfigs?: Record<string, PageConfig> | PageConfigFunction;\n __forceBuildStrategy?: string;\n}\n\n// 主要导出类型\nexport type Options = MultiPageOptions;\n\n// 开发服务器选项\nexport interface DevServerOptions {\n entry: string;\n exclude: string[];\n template: string;\n placeholder: string;\n strategies?: Record<string, ConfigStrategy>;\n pageConfigs?: Record<string, PageConfig> | PageConfigFunction;\n appliedStrategies?: Map<string, string>;\n}\n\n// 构建配置选项\nexport interface BuildConfigOptions {\n entry: string;\n exclude: string[];\n template: string;\n placeholder: string;\n strategies?: Record<string, ConfigStrategy>;\n pageConfigs?: Record<string, PageConfig> | PageConfigFunction;\n forceBuildStrategy?: string;\n}\n\n// 策略配置\nexport interface ConfigStrategy extends Omit<UserConfig, 'plugins'> {}\n\n// 页面配置\nexport interface PageConfig {\n strategy?: string;\n define?: Record<string, any>;\n template?: string;\n viteConfig?: UserConfig;\n match?: string;\n}\n\n// 页面上下文\nexport interface PageContext {\n pageName: string;\n filePath: string;\n relativePath: string;\n fullPath?: string;\n strategy?: string;\n isMatched?: boolean;\n}\n\n// 页面配置上下文(别名)\nexport type PageConfigContext = PageContext;\n\n// 页面配置函数\nexport type PageConfigFunction = (context: PageContext) => PageConfig | null;\n\n// 入口文件信息\nexport interface EntryFile {\n name: string;\n file: string;\n}\n\n// 候选文件信息\nexport interface CandidateFile extends EntryFile {\n priority: number;\n}\n\n// 构建策略配置\nexport interface BuildStrategyConfig {\n strategy: string;\n pages: string[];\n configPath?: string;\n}\n\n// CLI选项\nexport interface CLIOptions {\n configFile: string;\n outDir?: string;\n debug?: boolean;\n mode?: string;\n minify?: boolean | string;\n build?: Record<string, any>;\n base?: string;\n strategy?: string;\n port?: number | string;\n host?: string;\n https?: boolean;\n open?: boolean;\n}\n\n// 插件上下文\nexport interface PluginContext {\n mode: string;\n command: 'build' | 'serve';\n isCLI: boolean;\n}\n\n// 配置函数类型\nexport type ConfigFunction = (context: PluginContext) => MultiPageOptions;\n\n// 配置变换函数类型\nexport type ConfigTransformFunction = (\n config: MultiPageOptions,\n context: PluginContext\n) => MultiPageOptions;\n\n// 工具函数:定义配置\nexport function defineConfig(config: MultiPageOptions | ConfigFunction): ConfigFunction {\n // 如果传入的是函数,直接返回\n if (typeof config === 'function') {\n return config;\n }\n\n // 如果传入的是对象,包装成函数返回\n return () => config;\n}\n\n// 工具函数:定义配置变换\nexport function defineConfigTransform(transform: ConfigTransformFunction): ConfigTransformFunction {\n return transform;\n}\n"],"mappings":"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","names":["fs","import_vite","path","import_glob","path","fs","fs","path"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/dev-server.ts","../src/file-filter.ts","../src/utils.ts","../src/page-config.ts","../src/build-config.ts","../src/config-loader.ts","../src/defaults.ts","../src/types.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport type { Plugin } from 'vite';\nimport { mergeConfig } from 'vite';\nimport { setupDevMiddleware } from './dev-server';\nimport { generateBuildConfig } from './build-config';\nimport { loadUserConfig, hasCustomConfig } from './config-loader';\nimport { mergeWithDefaults } from './defaults';\nimport type { Options, ConfigTransformFunction } from './types';\n\n// 导出类型和工具函数\nexport { defineConfig, defineConfigTransform } from './types';\nexport type {\n ConfigFunction,\n ConfigTransformFunction,\n PluginContext,\n PageContext,\n PageConfig,\n} from './types';\n\nexport function viteMultiPage(transform?: ConfigTransformFunction): Plugin {\n let resolvedOptions: Options;\n const tempFiles: string[] = [];\n let log: (...args: any[]) => void = () => {}; // 默认为空函数\n\n return {\n name: 'vite-multi-page',\n\n async configResolved(config) {\n // 加载用户配置文件(如果存在)\n let userConfig: Options | null = null;\n\n if (hasCustomConfig()) {\n userConfig = await loadUserConfig({\n mode: config.command === 'serve' ? 'development' : 'production',\n command: config.command,\n isCLI: false,\n });\n }\n\n // 合并用户配置和默认配置\n const mergedConfig = mergeWithDefaults(userConfig);\n\n // 应用配置变换函数(如果提供)\n resolvedOptions = transform\n ? transform(mergedConfig, {\n mode: config.command === 'serve' ? 'development' : 'production',\n command: config.command,\n isCLI: false,\n })\n : mergedConfig;\n\n // 设置debug日志\n const debug = resolvedOptions.debug ?? false;\n log = debug ? console.log.bind(console, '[vite-multi-page]') : () => {};\n\n log('Vite配置已解析, 使用配置:', {\n strategies: Object.keys(resolvedOptions.strategies || {}),\n entry: resolvedOptions.entry,\n });\n },\n\n async config(config, { command }) {\n if (command === 'build') {\n // 在config钩子中临时加载配置,因为configResolved还没运行\n if (!resolvedOptions) {\n // 加载用户配置文件(如果存在)\n let userConfig: Options | null = null;\n\n if (hasCustomConfig()) {\n userConfig = await loadUserConfig({\n mode: 'production',\n command: 'build',\n isCLI: false,\n });\n }\n\n // 合并用户配置和默认配置\n const mergedConfig = mergeWithDefaults(userConfig);\n\n // 应用配置变换函数(如果提供)\n resolvedOptions = transform\n ? transform(mergedConfig, {\n mode: 'production',\n command: 'build',\n isCLI: false,\n })\n : mergedConfig;\n const debug = resolvedOptions.debug ?? false;\n log = debug ? console.log.bind(console, '[vite-multi-page]') : () => {};\n }\n\n log('配置构建模式');\n\n // 生成构建配置\n const forceBuildStrategy = process.env.VITE_BUILD_STRATEGY;\n const buildConfigs = generateBuildConfig({\n entry: resolvedOptions.entry || 'src/pages/**/*.{ts,js}',\n exclude: resolvedOptions.exclude || [],\n template: resolvedOptions.template || 'index.html',\n placeholder: resolvedOptions.placeholder || '{{ENTRY_FILE}}',\n strategies: resolvedOptions.strategies || {},\n pageConfigs: resolvedOptions.pageConfigs || {},\n forceBuildStrategy,\n });\n\n // 应用构建配置中的策略(如果有forceBuildStrategy,buildConfigs只会包含该策略)\n const targetStrategy = Object.keys(buildConfigs)[0];\n\n if (targetStrategy && buildConfigs[targetStrategy]) {\n log(`应用构建策略: ${targetStrategy}`);\n const strategyConfig = buildConfigs[targetStrategy];\n\n // 使用Vite的mergeConfig进行智能深度合并\n const mergedConfig = mergeConfig(config, strategyConfig);\n\n // 将合并结果复制回config对象\n Object.assign(config, mergedConfig);\n\n log(`已应用策略 \"${targetStrategy}\" 的配置:`, {\n build: !!strategyConfig.build,\n define: !!strategyConfig.define,\n plugins: strategyConfig.plugins?.length || 0,\n });\n } else {\n log('未找到可用的构建策略,使用默认配置');\n\n throw new Error(\n '❌ 构建失败: 未找到任何构建策略\\n\\n' +\n '可能的原因:\\n' +\n ' 1. 配置文件返回空对象 {}\\n' +\n ' 2. 未找到匹配的入口文件\\n' +\n ' 3. 模板文件不存在\\n' +\n ' 4. 未配置 strategies 对象\\n\\n' +\n '最小配置示例:\\n' +\n 'export default () => ({\\n' +\n ' entry: \"src/pages/**/*.{ts,js}\",\\n' +\n ' template: \"index.html\",\\n' +\n ' strategies: {\\n' +\n ' default: {}\\n' +\n ' }\\n' +\n '});'\n );\n }\n }\n },\n\n configureServer(server) {\n if (server.config.command === 'serve') {\n log('配置开发服务器');\n\n setupDevMiddleware(\n server,\n {\n entry: resolvedOptions.entry || 'src/pages/**/*.{ts,js}',\n exclude: resolvedOptions.exclude || [],\n template: resolvedOptions.template || 'index.html',\n placeholder: resolvedOptions.placeholder || '{{ENTRY_FILE}}',\n strategies: resolvedOptions.strategies || {},\n pageConfigs: resolvedOptions.pageConfigs || {},\n },\n log\n );\n }\n },\n\n buildEnd() {\n // 清理临时文件\n if (tempFiles.length > 0) {\n log(`清理 ${tempFiles.length} 个临时文件`);\n tempFiles.forEach(file => {\n try {\n if (fs.existsSync(file)) {\n fs.unlinkSync(file);\n log(`删除临时文件: ${file}`);\n }\n } catch (error) {\n log(`删除临时文件失败: ${file}`, error);\n }\n });\n tempFiles.length = 0;\n }\n },\n };\n}\n\nexport default viteMultiPage;\nexport type { Options } from './types';\nexport { generateBuildConfig, getAvailableStrategies } from './build-config';\nexport { mergeWithDefaults } from './defaults';\n","import type { ViteDevServer } from 'vite';\nimport * as path from 'node:path';\nimport * as fs from 'node:fs';\nimport { glob } from 'glob';\nimport { filterEntryFiles } from './file-filter';\nimport { escapeRegExp } from './utils';\nimport { DevServerOptions, PageConfigContext } from './types';\nimport { getPageConfig } from './page-config';\n\nexport function configureDevServer(\n server: ViteDevServer,\n options: DevServerOptions,\n log: (...args: any[]) => void\n) {\n try {\n const allFiles = glob.sync(options.entry, { cwd: process.cwd() });\n let entryFiles = filterEntryFiles(allFiles, options.entry, options.exclude, log);\n\n if (entryFiles.length === 0) {\n log('警告: 未找到匹配的入口文件');\n return;\n }\n\n // 获取指定的策略,优先使用命令行参数\n const cliStrategy = ((server.config as any).__cliStrategy ||\n (server.config as any).strategy) as string | undefined;\n\n // 如果指定了策略,则只显示该策略下的页面或没有指定策略的默认页面\n if (cliStrategy) {\n log(`开发服务器使用指定的策略: ${cliStrategy}`);\n\n // 过滤入口文件,只保留匹配策略的页面\n entryFiles = entryFiles.filter(file => {\n const pageName = file.name;\n const pageStrategy = options.appliedStrategies?.get(pageName) || undefined;\n\n // 在指定策略为default时,包含所有没有指定策略的页面\n if (cliStrategy === 'default') {\n return !pageStrategy || pageStrategy === 'default';\n }\n\n // 其他策略,只包含匹配的页面\n return pageStrategy === cliStrategy;\n });\n\n log(`策略 \"${cliStrategy}\" 下可用的页面: ${entryFiles.map(f => f.name).join(', ') || '无'}`);\n }\n\n log('开发服务器应用的入口文件:', entryFiles);\n\n // 修改中间件来处理HTML请求\n server.middlewares.use(async (req, res, next) => {\n try {\n const url = req.url || '';\n const pathWithoutQuery = url.split('?')[0];\n\n // 处理根路径请求 - 显示所有页面的索引\n if (pathWithoutQuery === '/') {\n const indexHtml = generateIndexHtml(entryFiles, options, log);\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/html');\n res.end(indexHtml);\n return;\n }\n\n // 跳过明显的静态资源请求\n if (\n pathWithoutQuery.match(/\\.(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)$/) &&\n !pathWithoutQuery.endsWith('.html')\n ) {\n return next();\n }\n\n // 提取页面名称,同时处理带.html后缀和不带后缀的情况\n let pageName = '';\n if (pathWithoutQuery.endsWith('.html')) {\n pageName = path.basename(pathWithoutQuery, '.html');\n } else if (pathWithoutQuery.startsWith('/')) {\n // 处理无扩展名的路径,如 /mobile\n pageName = pathWithoutQuery.substring(1); // 移除开头的斜杠\n }\n\n if (!pageName) {\n return next();\n }\n\n const matchedFile = entryFiles.find(file => file.name === pageName);\n\n if (!matchedFile) {\n return next();\n }\n\n // 获取页面配置\n const pageContext = {\n pageName: matchedFile.name,\n filePath: matchedFile.file,\n relativePath: path.relative(process.cwd(), matchedFile.file),\n strategy: undefined,\n isMatched: false,\n } as PageConfigContext;\n\n const pageConfig = getPageConfig(options.pageConfigs, pageContext, log);\n\n // 应用配置策略\n if (pageConfig?.strategy) {\n pageContext.strategy = pageConfig.strategy;\n } else if (options.appliedStrategies?.has(pageName)) {\n // 使用缓存的策略信息\n const strategyName = options.appliedStrategies.get(pageName);\n if (strategyName) {\n pageContext.strategy = strategyName;\n }\n }\n\n // 获取模板文件路径\n // 首先检查是否有页面特定的模板(例如mobile.html对应mobile页面)\n let templatePath = '';\n\n // 尝试以页面名称查找匹配的模板\n const pageSpecificTemplate = path.resolve(process.cwd(), `${pageName}.html`);\n if (fs.existsSync(pageSpecificTemplate)) {\n templatePath = pageSpecificTemplate;\n }\n // 然后尝试使用页面配置中指定的模板\n else if (pageConfig?.template) {\n templatePath = path.resolve(process.cwd(), pageConfig.template);\n }\n // 最后使用默认模板\n else {\n templatePath = path.resolve(process.cwd(), options.template);\n }\n\n if (!fs.existsSync(templatePath)) {\n return next();\n }\n\n // 读取并修改模板\n let html = fs.readFileSync(templatePath, 'utf-8');\n\n // 检查模板中是否包含占位符\n const containsPlaceholder = html.includes(options.placeholder);\n\n // 替换占位符为入口文件路径\n if (containsPlaceholder) {\n const originalHtml = html;\n\n // 方式1: 直接字符串替换\n html = html.split(options.placeholder).join(`/${matchedFile.file}`);\n\n // 检查替换结果\n if (html === originalHtml) {\n // 方式2: 正则表达式替换\n const escapedPlaceholder = escapeRegExp(options.placeholder);\n const placeholderRegex = new RegExp(escapedPlaceholder, 'g');\n html = originalHtml.replace(placeholderRegex, `/${matchedFile.file}`);\n\n // 检查替换结果\n if (html === originalHtml) {\n // 方式3: 硬编码替换具体的占位符格式\n html = originalHtml.replace(/\\{\\{ENTRY_FILE\\}\\}/g, `/${matchedFile.file}`);\n }\n }\n }\n\n // 添加页面级define变量\n if (pageConfig?.define) {\n const defineScript = Object.entries(pageConfig.define)\n .map(([key, value]) => {\n const stringValue = typeof value === 'string' ? `\"${value}\"` : JSON.stringify(value);\n return `window.${key} = ${stringValue};`;\n })\n .join('\\n');\n\n if (defineScript) {\n // 注入到head标签底部\n html = html.replace(\n /<\\/head>/i,\n `<script type=\"text/javascript\">\\n${defineScript}\\n</script>\\n</head>`\n );\n }\n }\n\n // 发送响应\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/html');\n res.end(html);\n } catch (error) {\n log(`开发服务器处理请求失败: ${error}`);\n next(error);\n }\n });\n\n log('开发服务器配置完成');\n } catch (error) {\n log(`配置开发服务器失败: ${error}`);\n throw error;\n }\n}\n\n// 为了兼容性,导出setupDevMiddleware作为configureDevServer的别名\nexport const setupDevMiddleware = configureDevServer;\n\n// 生成索引页面HTML\nfunction generateIndexHtml(\n entryFiles: { name: string; file: string }[],\n options: DevServerOptions,\n log: (...args: any[]) => void\n): string {\n try {\n const pageItems = entryFiles\n .map(file => {\n // 获取页面配置和策略\n const pageContext = {\n pageName: file.name,\n filePath: file.file,\n relativePath: path.relative(process.cwd(), file.file),\n strategy: undefined,\n isMatched: false,\n };\n\n const pageConfig = getPageConfig(options.pageConfigs, pageContext, log);\n\n // 确定策略\n let strategy = 'default';\n if (pageConfig?.strategy) {\n strategy = pageConfig.strategy;\n } else if (options.appliedStrategies?.has(file.name)) {\n const strategyName = options.appliedStrategies.get(file.name);\n if (strategyName) {\n strategy = strategyName;\n }\n }\n\n const strategyBadge =\n strategy !== 'default' ? `<span class=\"badge\">${strategy}</span>` : '';\n\n return `\n <div class=\"page-item\">\n <a href=\"${file.name}.html\" class=\"page-link\">\n ${file.name}${strategyBadge}\n </a>\n <div class=\"page-path\">${file.file}</div>\n </div>`;\n })\n .join('');\n\n return `\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>多页面应用索引</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;\n line-height: 1.6;\n color: #333;\n max-width: 1200px;\n margin: 0 auto;\n padding: 20px;\n background-color: #f5f5f7;\n }\n h1 {\n font-size: 24px;\n margin-bottom: 20px;\n color: #111;\n }\n .page-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n }\n .page-item {\n background-color: white;\n border-radius: 8px;\n padding: 16px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.1);\n transition: transform 0.2s, box-shadow 0.2s;\n }\n .page-item:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 8px rgba(0,0,0,0.1);\n }\n .page-link {\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 18px;\n font-weight: 500;\n color: #0066cc;\n text-decoration: none;\n margin-bottom: 8px;\n }\n .page-path {\n font-size: 14px;\n color: #666;\n word-break: break-all;\n }\n .badge {\n display: inline-block;\n font-size: 12px;\n padding: 2px 8px;\n border-radius: 12px;\n background-color: #e6f2ff;\n color: #0066cc;\n margin-left: 8px;\n }\n .stats {\n margin-bottom: 20px;\n font-size: 14px;\n color: #666;\n }\n </style>\n </head>\n <body>\n <h1>多页面应用索引</h1>\n <div class=\"stats\">\n 找到 ${entryFiles.length} 个页面\n </div>\n <div class=\"page-list\">\n ${pageItems}\n </div>\n </body>\n </html>\n `;\n } catch (error) {\n log(`生成索引页失败: ${error}`);\n return `\n <!DOCTYPE html>\n <html>\n <head>\n <title>错误</title>\n </head>\n <body>\n <h1>生成索引页时发生错误</h1>\n <p>${error}</p>\n </body>\n </html>\n `;\n }\n}\n","import * as path from 'node:path';\nimport type { EntryFile, CandidateFile } from './types';\n\nexport function filterEntryFiles(\n files: string[],\n entry: string,\n exclude: string[],\n _log: (...args: any[]) => void\n): EntryFile[] {\n const result: EntryFile[] = [];\n const nameToFile = new Map<string, { file: string; priority: number }>();\n\n // 从entry模式中提取基础目录\n let basePattern = entry.replace(/\\/\\*.*$/, ''); // 去掉glob部分\n // 如果基础模式为空或不合理,使用默认处理\n if (!basePattern || basePattern === entry) {\n basePattern = path.dirname(entry.split('*')[0]);\n }\n const candidateFiles: CandidateFile[] = [];\n\n for (const file of files) {\n if (exclude.includes(file)) {\n continue;\n }\n\n const relativePath = path.relative(basePattern, file);\n const pathParts = relativePath.split(path.sep);\n\n if (pathParts.length === 1) {\n // 第一级文件:src/pages/about.js -> /about.html\n const fileName = pathParts[0];\n const name = path.basename(fileName, path.extname(fileName));\n candidateFiles.push({ name, file, priority: 1 });\n } else if (pathParts.length >= 2) {\n // 目录下的文件\n const fileName = path.basename(file, path.extname(file));\n const dirName = pathParts[0];\n\n if (fileName === 'main') {\n // 目录下的main文件:src/pages/mobile/main.ts -> /mobile.html\n candidateFiles.push({ name: dirName, file, priority: 2 });\n }\n }\n }\n\n // 按照优先级处理冲突:目录优先覆盖文件(优先级2 > 优先级1)\n for (const candidate of candidateFiles) {\n const existing = nameToFile.get(candidate.name);\n\n if (!existing) {\n nameToFile.set(candidate.name, { file: candidate.file, priority: candidate.priority });\n } else {\n if (candidate.priority > existing.priority) {\n nameToFile.set(candidate.name, { file: candidate.file, priority: candidate.priority });\n }\n }\n }\n\n for (const [name, { file }] of nameToFile.entries()) {\n result.push({ name, file });\n }\n\n return result;\n}\n","export function escapeRegExp(string: string): string {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function createLogger(debug: boolean) {\n return (...args: any[]) => {\n if (debug) {\n console.log('[vite-plugin-multi-page]', ...args);\n }\n };\n}\n","import type { PageConfig, PageConfigFunction, PageConfigContext } from './types';\n\n/**\n * 根据页面上下文获取页面配置\n */\nexport function getPageConfig(\n pageConfigs: Record<string, PageConfig> | PageConfigFunction | undefined,\n context: PageConfigContext,\n log: (...args: any[]) => void\n): PageConfig | null {\n if (!pageConfigs) return null;\n\n // 如果是函数,直接调用\n if (typeof pageConfigs === 'function') {\n const result = pageConfigs(context);\n if (result) {\n // log(`函数配置匹配页面 ${context.pageName}:`, result);\n }\n return result;\n }\n\n // 对象配置:支持精确匹配和模式匹配\n for (const [key, config] of Object.entries(pageConfigs)) {\n // 精确匹配页面名称\n if (key === context.pageName) {\n log(`精确匹配页面 ${context.pageName}:`, config);\n return config;\n }\n\n // 模式匹配\n if (config.match) {\n const patterns = Array.isArray(config.match) ? config.match : [config.match];\n const isMatched = patterns.some(\n pattern =>\n simpleMatch(pattern, context.pageName) ||\n simpleMatch(pattern, context.relativePath) ||\n simpleMatch(pattern, context.filePath)\n );\n\n if (isMatched) {\n log(`模式匹配页面 ${context.pageName} (模式: ${config.match}):`, config);\n return { ...config, match: undefined };\n }\n }\n\n // glob 模式匹配页面名称\n if (simpleMatch(key, context.pageName)) {\n log(`Glob匹配页面 ${context.pageName} (模式: ${key}):`, config);\n return config;\n }\n }\n\n return null;\n}\n\n/**\n * 简单的模式匹配函数\n */\nfunction simpleMatch(pattern: string, text: string): boolean {\n const regexPattern = pattern\n .replace(/\\*\\*/g, '__DOUBLE_STAR__')\n .replace(/\\*/g, '[^/]*')\n .replace(/__DOUBLE_STAR__/g, '.*');\n const regex = new RegExp(`^${regexPattern}$`);\n return regex.test(text);\n}\n","import type { UserConfig } from 'vite';\nimport { mergeConfig } from 'vite';\nimport { glob } from 'glob';\nimport * as path from 'node:path';\nimport * as fs from 'node:fs';\nimport { filterEntryFiles } from './file-filter';\nimport { getPageConfig } from './page-config';\nimport type { BuildConfigOptions, PageConfigContext, ConfigStrategy } from './types';\nimport { createLogger } from './utils';\n\n/**\n * 构建时配置生成器\n * 根据策略和页面配置生成多页面构建配置\n */\nexport function generateBuildConfig(options: BuildConfigOptions): Record<string, UserConfig> {\n const {\n entry = 'src/pages/*/main.{ts,js}',\n exclude = [],\n template = 'index.html',\n placeholder = '<!--VITE_MULTI_PAGE_ENTRY-->',\n strategies = {},\n pageConfigs = {},\n forceBuildStrategy,\n } = options;\n\n const log = createLogger(true);\n const buildConfigs: Record<string, UserConfig> = {};\n\n try {\n // 1. 发现所有页面入口文件\n const allFiles = glob.sync(entry, { cwd: process.cwd() });\n const entryFiles = filterEntryFiles(allFiles, entry, exclude, log);\n\n if (entryFiles.length === 0) {\n log('警告: 未找到匹配的入口文件');\n return {};\n }\n\n // 2. 为每个页面分析配置和策略\n const pageStrategies = new Map<string, string>();\n const strategyPages = new Map<string, string[]>();\n\n for (const entryFile of entryFiles) {\n const pageContext = {\n pageName: entryFile.name,\n filePath: entryFile.file,\n relativePath: path.relative(process.cwd(), entryFile.file),\n } as PageConfigContext;\n\n // 获取页面配置\n const pageConfig = getPageConfig(pageConfigs, pageContext, log);\n const strategyName = pageConfig?.strategy || 'default';\n\n pageStrategies.set(entryFile.name, strategyName);\n\n if (!strategyPages.has(strategyName)) {\n strategyPages.set(strategyName, []);\n }\n strategyPages.get(strategyName)?.push(entryFile.name);\n }\n\n log(`📄 发现 ${entryFiles.length} 个页面: ${entryFiles.map(f => f.name).join(', ')}`);\n\n // 3. 如果指定了强制策略,只构建该策略的页面\n if (forceBuildStrategy) {\n const targetPages = strategyPages.get(forceBuildStrategy) || [];\n if (targetPages.length === 0) {\n log(`警告: 策略 \"${forceBuildStrategy}\" 下没有页面`);\n return {};\n }\n\n log(`强制构建策略: ${forceBuildStrategy}, 页面: ${targetPages.join(', ')}`);\n\n const config = generateStrategyConfig(\n forceBuildStrategy,\n targetPages,\n entryFiles,\n strategies[forceBuildStrategy],\n pageConfigs,\n template,\n placeholder,\n log\n );\n\n buildConfigs[forceBuildStrategy] = config;\n return buildConfigs;\n }\n\n // 4. 为每个策略生成构建配置\n for (const [strategyName, pages] of strategyPages) {\n if (pages.length === 0) continue;\n\n // 获取策略配置,如果没有定义则使用空配置(允许默认策略)\n const strategyConfig = strategies[strategyName] || {};\n const config = generateStrategyConfig(\n strategyName,\n pages,\n entryFiles,\n strategyConfig,\n pageConfigs,\n template,\n placeholder,\n log\n );\n\n buildConfigs[strategyName] = config;\n }\n\n // 确保至少有一个构建配置\n if (Object.keys(buildConfigs).length === 0) {\n log('警告: 未生成任何构建配置,创建默认配置');\n\n // 如果没有任何策略,创建一个默认策略包含所有页面\n const allPageNames = entryFiles.map(f => f.name);\n const defaultConfig = generateStrategyConfig(\n 'default',\n allPageNames,\n entryFiles,\n {},\n pageConfigs,\n template,\n placeholder,\n log\n );\n\n buildConfigs['default'] = defaultConfig;\n }\n\n const strategyNames = Object.keys(buildConfigs);\n log(`📦 构建策略: ${strategyNames.join(', ')}`);\n return buildConfigs;\n } catch (error) {\n log('生成构建配置失败:', error);\n throw error;\n }\n}\n\n/**\n * 为特定策略生成构建配置\n */\nfunction generateStrategyConfig(\n strategyName: string,\n pages: string[],\n entryFiles: Array<{ name: string; file: string }>,\n strategyConfig: ConfigStrategy | undefined,\n pageConfigs: any,\n defaultTemplate: string,\n placeholder: string,\n log: (...args: any[]) => void\n): UserConfig {\n const htmlInputs: Record<string, string> = {};\n const tempFiles: string[] = [];\n\n // 收集所有页面的 define 变量\n const allPageDefines: Record<string, any> = {};\n\n // 为每个页面确定使用的HTML模板并创建临时文件\n for (const pageName of pages) {\n const entryFile = entryFiles.find(f => f.name === pageName);\n if (!entryFile) continue;\n\n // 获取页面配置\n const pageContext = {\n pageName,\n filePath: entryFile.file,\n relativePath: path.relative(process.cwd(), entryFile.file),\n strategy: strategyName,\n } as PageConfigContext;\n\n const pageConfig = getPageConfig(pageConfigs, pageContext, log);\n\n // 收集页面级 define 变量\n if (pageConfig?.define) {\n Object.assign(allPageDefines, pageConfig.define);\n }\n\n // 确定HTML模板\n let templatePath = defaultTemplate;\n\n // 1. 页面特定模板(如 mobile.html 对应 mobile 页面)\n const pageSpecificTemplate = `${pageName}.html`;\n if (fs.existsSync(path.resolve(process.cwd(), pageSpecificTemplate))) {\n templatePath = pageSpecificTemplate;\n }\n // 2. 页面配置中指定的模板\n else if (pageConfig?.template) {\n templatePath = pageConfig.template;\n }\n\n // 读取模板内容\n const templateFullPath = path.resolve(process.cwd(), templatePath);\n if (!fs.existsSync(templateFullPath)) {\n log(`警告: 模板文件不存在: ${templatePath}`);\n continue;\n }\n\n let templateContent = fs.readFileSync(templateFullPath, 'utf-8');\n\n // 替换占位符\n if (templateContent.includes(placeholder)) {\n // 临时HTML在项目根目录中,使用相对路径\n const entryPath = `./${entryFile.file}`;\n templateContent = templateContent.replace(\n new RegExp(placeholder.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'g'),\n entryPath\n );\n }\n\n // 创建临时HTML文件,使用新的命名规则:.temp.mp.[name].html\n const tempHtmlPath = path.resolve(process.cwd(), `.temp.mp.${pageName}.html`);\n fs.writeFileSync(tempHtmlPath, templateContent);\n tempFiles.push(tempHtmlPath);\n\n htmlInputs[pageName] = tempHtmlPath;\n }\n\n // 构建基础配置\n const baseConfig: UserConfig = {\n build: {\n rollupOptions: {\n input: htmlInputs, // 使用临时HTML文件作为输入\n output: {\n entryFileNames: 'assets/[name]-[hash].js',\n chunkFileNames: 'assets/[name]-[hash].js',\n assetFileNames: 'assets/[name]-[hash][extname]',\n },\n },\n outDir: `dist/${strategyName}`, // 直接输出到策略目录\n emptyOutDir: false, // 不清空输出目录,避免删除临时HTML文件\n },\n define: {},\n };\n\n // 使用Vite的mergeConfig进行智能深度合并\n let config: UserConfig = baseConfig;\n\n if (strategyConfig) {\n config = mergeConfig(baseConfig, strategyConfig);\n }\n\n // 合并页面级 define 变量到 Vite 的 define 配置中\n // 页面级 define 优先级高于策略级 define\n if (Object.keys(allPageDefines).length > 0) {\n config.define = {\n ...config.define,\n ...allPageDefines,\n };\n }\n\n // 手动处理需要特殊控制的配置项,防止被mergeConfig覆盖\n if (!config.build) config.build = {};\n if (!config.build.rollupOptions) config.build.rollupOptions = {};\n\n // 确保关键配置不被覆盖\n config.build.outDir = `dist/${strategyName}`; // 强制设置正确的输出目录\n config.build.rollupOptions.input = htmlInputs; // 强制使用临时HTML文件作为输入\n config.build.emptyOutDir = false; // 不清空输出目录,避免删除临时HTML文件\n\n // 简化日志输出\n log(`策略 \"${strategyName}\" - ${pages.length} 个页面`);\n\n return config;\n}\n\n/**\n * 获取所有可用的构建策略\n */\nexport function getAvailableStrategies(options: BuildConfigOptions): string[] {\n const { entry = 'src/pages/*/main.{ts,js}', exclude = [], pageConfigs = {} } = options;\n\n const log = createLogger(false); // 静默模式\n const strategySet = new Set<string>();\n\n try {\n // 发现所有页面入口文件\n const allFiles = glob.sync(entry, { cwd: process.cwd() });\n const entryFiles = filterEntryFiles(allFiles, entry, exclude, log);\n\n // 分析每个页面的策略\n for (const entryFile of entryFiles) {\n const pageContext = {\n pageName: entryFile.name,\n filePath: entryFile.file,\n relativePath: path.relative(process.cwd(), entryFile.file),\n } as PageConfigContext;\n\n const pageConfig = getPageConfig(pageConfigs, pageContext, log);\n const strategyName = pageConfig?.strategy || 'default';\n strategySet.add(strategyName);\n }\n\n // 只返回实际有页面的策略,不添加空策略\n return Array.from(strategySet).sort();\n } catch (error) {\n log('获取可用策略失败:', error);\n return ['default'];\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { Module } from 'node:module';\nimport type { Options } from './types';\n\n/**\n * 配置上下文\n */\nexport interface ConfigContext {\n mode: 'development' | 'production';\n command: 'serve' | 'build';\n isCLI?: boolean;\n}\n\n/**\n * 配置函数类型\n */\nexport type ConfigFunction = (context: ConfigContext) => Options;\n\n/**\n * 配置文件名列表(优先级从高到低)\n */\nconst CONFIG_FILES = [\n 'multipage.config.js',\n 'multipage.config.mjs',\n 'multipage.config.ts',\n] as const;\n\n/**\n * 检查是否存在自定义配置文件\n */\nexport function hasCustomConfig(): boolean {\n for (const filename of CONFIG_FILES) {\n const configPath = path.resolve(process.cwd(), filename);\n if (fs.existsSync(configPath)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * 加载用户的多页面配置\n */\nexport async function loadUserConfig(context: ConfigContext): Promise<Options | null> {\n // 尝试加载项目自定义配置\n const customConfig = await loadCustomConfig();\n\n if (customConfig) {\n // 使用项目自定义配置\n const result = customConfig(context);\n\n // 如果配置函数返回 undefined 或 null,视为空配置\n if (!result) {\n return {};\n }\n\n return result;\n }\n\n // 没有找到用户配置\n return null;\n}\n\n/**\n * 加载配置文件\n */\nasync function loadConfigFile(filePath: string): Promise<any> {\n // 处理 TypeScript 文件\n if (filePath.endsWith('.ts')) {\n try {\n const code = await fs.promises.readFile(filePath, 'utf-8');\n\n // 使用 esbuild 实时转译 TS → JS\n const esbuild = (await import('esbuild')) as any;\n const result = await esbuild.transform(code, {\n loader: 'ts',\n format: 'cjs', // 使用 CommonJS 格式便于使用 Module._compile\n target: 'node16',\n sourcemap: false,\n });\n\n // 创建临时模块并编译\n const tempModule = new Module(filePath);\n tempModule.filename = filePath;\n tempModule.paths = (Module as any)._nodeModulePaths(path.dirname(filePath));\n\n // 编译代码\n (tempModule as any)._compile(result.code, filePath);\n\n return tempModule.exports;\n } catch (esbuildError) {\n console.warn('esbuild 转译失败,尝试简单转换:', esbuildError);\n\n // 备选方案:简单的文本替换\n const code = await fs.promises.readFile(filePath, 'utf-8');\n const jsCode = code\n .replace(/export\\s+default\\s+/, 'module.exports = ')\n .replace(/import\\s+.*?from\\s+['\"][^'\"]*['\"];?\\s*/g, '')\n .replace(/:\\s*[^=,})\\]]+/g, ''); // 简单的类型注解移除\n\n const tempModule = new Module(filePath);\n tempModule.filename = filePath;\n tempModule.paths = (Module as any)._nodeModulePaths(path.dirname(filePath));\n\n (tempModule as any)._compile(jsCode, filePath);\n return tempModule.exports;\n }\n }\n\n // 处理 JavaScript 文件\n if (filePath.endsWith('.js') || filePath.endsWith('.mjs')) {\n const fileUrl = pathToFileURL(filePath).href;\n return import(`${fileUrl}?t=${Date.now()}`);\n }\n\n throw new Error(`不支持的配置文件类型: ${filePath}`);\n}\n\n/**\n * 加载项目自定义配置文件\n */\nasync function loadCustomConfig(): Promise<ConfigFunction | null> {\n const cwd = process.cwd();\n\n for (const configFile of CONFIG_FILES) {\n const configPath = path.resolve(cwd, configFile);\n\n if (fs.existsSync(configPath)) {\n try {\n const configModule = await loadConfigFile(configPath);\n const configFunction = configModule.default || configModule;\n\n if (typeof configFunction === 'function') {\n return configFunction;\n } else {\n console.warn(`配置文件 ${configFile} 必须默认导出一个函数`);\n }\n } catch (error) {\n if (configFile.endsWith('.ts')) {\n console.error(`加载TypeScript配置文件 ${configFile} 失败:`, error);\n console.log('提示:确保你的项目支持TypeScript,或者使用 .js/.mjs 配置文件');\n } else {\n console.error(`加载配置文件 ${configFile} 失败:`, error);\n }\n }\n }\n }\n\n return null;\n}\n","import type { MultiPageOptions } from './types';\n\n/**\n * 默认配置选项\n */\nexport const DEFAULT_CONFIG: Required<Omit<MultiPageOptions, '__forceBuildStrategy'>> = {\n entry: 'src/pages/**/*.{ts,js}',\n exclude: [],\n template: 'index.html',\n placeholder: '{{ENTRY_FILE}}',\n debug: false,\n strategies: {\n default: {},\n },\n pageConfigs: {},\n};\n\n/**\n * 合并用户配置和默认配置\n */\nexport function mergeWithDefaults(\n userConfig: MultiPageOptions | null | undefined\n): MultiPageOptions {\n if (!userConfig) {\n return { ...DEFAULT_CONFIG };\n }\n\n return {\n entry: userConfig.entry ?? DEFAULT_CONFIG.entry,\n exclude: userConfig.exclude ?? DEFAULT_CONFIG.exclude,\n template: userConfig.template ?? DEFAULT_CONFIG.template,\n placeholder: userConfig.placeholder ?? DEFAULT_CONFIG.placeholder,\n debug: userConfig.debug ?? DEFAULT_CONFIG.debug,\n strategies: userConfig.strategies ?? DEFAULT_CONFIG.strategies,\n pageConfigs: userConfig.pageConfigs ?? DEFAULT_CONFIG.pageConfigs,\n __forceBuildStrategy: userConfig.__forceBuildStrategy,\n };\n}\n\n/**\n * 检查配置是否为空或无效\n */\nexport function isEmptyConfig(config: MultiPageOptions): boolean {\n // 检查是否是完全空的对象\n if (Object.keys(config).length === 0) {\n return true;\n }\n\n // 检查是否只有默认值或无效值\n const hasValidEntry = config.entry && config.entry !== DEFAULT_CONFIG.entry;\n const hasValidStrategies = config.strategies && Object.keys(config.strategies).length > 0;\n const hasValidPageConfigs =\n config.pageConfigs &&\n (typeof config.pageConfigs === 'function' || Object.keys(config.pageConfigs).length > 0);\n\n return !hasValidEntry && !hasValidStrategies && !hasValidPageConfigs;\n}\n","import type { UserConfig } from 'vite';\n\n// 核心配置选项\nexport interface MultiPageOptions {\n entry?: string;\n exclude?: string[];\n template?: string;\n placeholder?: string;\n debug?: boolean;\n strategies?: Record<string, ConfigStrategy>;\n pageConfigs?: Record<string, PageConfig> | PageConfigFunction;\n __forceBuildStrategy?: string;\n}\n\n// 主要导出类型\nexport type Options = MultiPageOptions;\n\n// 开发服务器选项\nexport interface DevServerOptions {\n entry: string;\n exclude: string[];\n template: string;\n placeholder: string;\n strategies?: Record<string, ConfigStrategy>;\n pageConfigs?: Record<string, PageConfig> | PageConfigFunction;\n appliedStrategies?: Map<string, string>;\n}\n\n// 构建配置选项\nexport interface BuildConfigOptions {\n entry: string;\n exclude: string[];\n template: string;\n placeholder: string;\n strategies?: Record<string, ConfigStrategy>;\n pageConfigs?: Record<string, PageConfig> | PageConfigFunction;\n forceBuildStrategy?: string;\n}\n\n// 策略配置\nexport interface ConfigStrategy extends Omit<UserConfig, 'plugins'> {}\n\n// 页面配置\nexport interface PageConfig {\n strategy?: string;\n define?: Record<string, any>;\n template?: string;\n viteConfig?: UserConfig;\n match?: string;\n}\n\n// 页面上下文\nexport interface PageContext {\n pageName: string;\n filePath: string;\n relativePath: string;\n fullPath?: string;\n strategy?: string;\n isMatched?: boolean;\n}\n\n// 页面配置上下文(别名)\nexport type PageConfigContext = PageContext;\n\n// 页面配置函数\nexport type PageConfigFunction = (context: PageContext) => PageConfig | null;\n\n// 入口文件信息\nexport interface EntryFile {\n name: string;\n file: string;\n}\n\n// 候选文件信息\nexport interface CandidateFile extends EntryFile {\n priority: number;\n}\n\n// 构建策略配置\nexport interface BuildStrategyConfig {\n strategy: string;\n pages: string[];\n configPath?: string;\n}\n\n// CLI选项\nexport interface CLIOptions {\n configFile: string;\n outDir?: string;\n debug?: boolean;\n mode?: string;\n minify?: boolean | string;\n build?: Record<string, any>;\n base?: string;\n strategy?: string;\n port?: number | string;\n host?: string;\n https?: boolean;\n open?: boolean;\n}\n\n// 插件上下文\nexport interface PluginContext {\n mode: string;\n command: 'build' | 'serve';\n isCLI: boolean;\n}\n\n// 配置函数类型\nexport type ConfigFunction = (context: PluginContext) => MultiPageOptions;\n\n// 配置变换函数类型\nexport type ConfigTransformFunction = (\n config: MultiPageOptions,\n context: PluginContext\n) => MultiPageOptions;\n\n// 工具函数:定义配置\nexport function defineConfig(config: MultiPageOptions | ConfigFunction): ConfigFunction {\n // 如果传入的是函数,直接返回\n if (typeof config === 'function') {\n return config;\n }\n\n // 如果传入的是对象,包装成函数返回\n return () => config;\n}\n\n// 工具函数:定义配置变换\nexport function defineConfigTransform(transform: ConfigTransformFunction): ConfigTransformFunction {\n return transform;\n}\n"],"mappings":"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","names":["fs","import_vite","path","import_glob","path","fs","fs","path"]}
|
package/dist/index.mjs
CHANGED
|
@@ -9,56 +9,39 @@ import { glob } from "glob";
|
|
|
9
9
|
|
|
10
10
|
// src/file-filter.ts
|
|
11
11
|
import * as path from "node:path";
|
|
12
|
-
function filterEntryFiles(files, entry, exclude,
|
|
12
|
+
function filterEntryFiles(files, entry, exclude, _log) {
|
|
13
13
|
const result = [];
|
|
14
14
|
const nameToFile = /* @__PURE__ */ new Map();
|
|
15
15
|
let basePattern = entry.replace(/\/\*.*$/, "");
|
|
16
16
|
if (!basePattern || basePattern === entry) {
|
|
17
17
|
basePattern = path.dirname(entry.split("*")[0]);
|
|
18
18
|
}
|
|
19
|
-
log("\u57FA\u7840\u76EE\u5F55\u6A21\u5F0F:", basePattern);
|
|
20
19
|
const candidateFiles = [];
|
|
21
20
|
for (const file of files) {
|
|
22
21
|
if (exclude.includes(file)) {
|
|
23
|
-
log(`\u8DF3\u8FC7\u6392\u9664\u6587\u4EF6: ${file}`);
|
|
24
22
|
continue;
|
|
25
23
|
}
|
|
26
24
|
const relativePath = path.relative(basePattern, file);
|
|
27
25
|
const pathParts = relativePath.split(path.sep);
|
|
28
|
-
log(`\u5904\u7406\u6587\u4EF6: ${file}`);
|
|
29
|
-
log(`\u76F8\u5BF9\u8DEF\u5F84: ${relativePath}`);
|
|
30
|
-
log(`\u8DEF\u5F84\u90E8\u5206: ${pathParts}`);
|
|
31
26
|
if (pathParts.length === 1) {
|
|
32
27
|
const fileName = pathParts[0];
|
|
33
28
|
const name = path.basename(fileName, path.extname(fileName));
|
|
34
29
|
candidateFiles.push({ name, file, priority: 1 });
|
|
35
|
-
log(`\u{1F4C4} \u7B2C\u4E00\u7EA7\u6587\u4EF6: ${file} -> ${name}.html (\u4F18\u5148\u7EA7: 1)`);
|
|
36
30
|
} else if (pathParts.length >= 2) {
|
|
37
31
|
const fileName = path.basename(file, path.extname(file));
|
|
38
32
|
const dirName = pathParts[0];
|
|
39
33
|
if (fileName === "main") {
|
|
40
34
|
candidateFiles.push({ name: dirName, file, priority: 2 });
|
|
41
|
-
log(`\u{1F4C1} \u76EE\u5F55main\u6587\u4EF6: ${file} -> ${dirName}.html (\u4F18\u5148\u7EA7: 2)`);
|
|
42
|
-
} else {
|
|
43
|
-
log(`\u274C \u8DF3\u8FC7\u6587\u4EF6: ${file} (\u4E0D\u662Fmain\u6587\u4EF6)`);
|
|
44
35
|
}
|
|
45
|
-
} else {
|
|
46
|
-
log(`\u274C \u8DF3\u8FC7\u6587\u4EF6: ${file} (\u8DEF\u5F84\u5C42\u7EA7\u4E0D\u7B26\u5408)`);
|
|
47
36
|
}
|
|
48
37
|
}
|
|
49
38
|
for (const candidate of candidateFiles) {
|
|
50
39
|
const existing = nameToFile.get(candidate.name);
|
|
51
40
|
if (!existing) {
|
|
52
41
|
nameToFile.set(candidate.name, { file: candidate.file, priority: candidate.priority });
|
|
53
|
-
log(`\u2705 \u6DFB\u52A0\u9875\u9762: ${candidate.name} -> ${candidate.file}`);
|
|
54
42
|
} else {
|
|
55
43
|
if (candidate.priority > existing.priority) {
|
|
56
44
|
nameToFile.set(candidate.name, { file: candidate.file, priority: candidate.priority });
|
|
57
|
-
log(
|
|
58
|
-
`\u{1F504} \u66FF\u6362\u9875\u9762: ${candidate.name} -> ${candidate.file} (\u66FF\u6362 ${existing.file}, \u76EE\u5F55\u4F18\u5148)`
|
|
59
|
-
);
|
|
60
|
-
} else {
|
|
61
|
-
log(`\u26A0\uFE0F \u51B2\u7A81\u8DF3\u8FC7: ${candidate.name} -> ${candidate.file} (\u4FDD\u7559 ${existing.file})`);
|
|
62
45
|
}
|
|
63
46
|
}
|
|
64
47
|
}
|
|
@@ -87,7 +70,6 @@ function getPageConfig(pageConfigs, context, log) {
|
|
|
87
70
|
if (typeof pageConfigs === "function") {
|
|
88
71
|
const result = pageConfigs(context);
|
|
89
72
|
if (result) {
|
|
90
|
-
log(`\u51FD\u6570\u914D\u7F6E\u5339\u914D\u9875\u9762 ${context.pageName}:`, result);
|
|
91
73
|
}
|
|
92
74
|
return result;
|
|
93
75
|
}
|
|
@@ -395,7 +377,6 @@ function generateBuildConfig(options) {
|
|
|
395
377
|
log("\u8B66\u544A: \u672A\u627E\u5230\u5339\u914D\u7684\u5165\u53E3\u6587\u4EF6");
|
|
396
378
|
return {};
|
|
397
379
|
}
|
|
398
|
-
log(`\u53D1\u73B0 ${entryFiles.length} \u4E2A\u9875\u9762\u5165\u53E3`);
|
|
399
380
|
const pageStrategies = /* @__PURE__ */ new Map();
|
|
400
381
|
const strategyPages = /* @__PURE__ */ new Map();
|
|
401
382
|
for (const entryFile of entryFiles) {
|
|
@@ -412,7 +393,7 @@ function generateBuildConfig(options) {
|
|
|
412
393
|
}
|
|
413
394
|
(_a = strategyPages.get(strategyName)) == null ? void 0 : _a.push(entryFile.name);
|
|
414
395
|
}
|
|
415
|
-
log(
|
|
396
|
+
log(`\u{1F4C4} \u53D1\u73B0 ${entryFiles.length} \u4E2A\u9875\u9762: ${entryFiles.map((f) => f.name).join(", ")}`);
|
|
416
397
|
if (forceBuildStrategy) {
|
|
417
398
|
const targetPages = strategyPages.get(forceBuildStrategy) || [];
|
|
418
399
|
if (targetPages.length === 0) {
|
|
@@ -436,7 +417,6 @@ function generateBuildConfig(options) {
|
|
|
436
417
|
for (const [strategyName, pages] of strategyPages) {
|
|
437
418
|
if (pages.length === 0)
|
|
438
419
|
continue;
|
|
439
|
-
log(`\u751F\u6210\u7B56\u7565 "${strategyName}" \u7684\u6784\u5EFA\u914D\u7F6E, \u9875\u9762: ${pages.join(", ")}`);
|
|
440
420
|
const strategyConfig = strategies[strategyName] || {};
|
|
441
421
|
const config = generateStrategyConfig(
|
|
442
422
|
strategyName,
|
|
@@ -465,7 +445,8 @@ function generateBuildConfig(options) {
|
|
|
465
445
|
);
|
|
466
446
|
buildConfigs["default"] = defaultConfig;
|
|
467
447
|
}
|
|
468
|
-
|
|
448
|
+
const strategyNames = Object.keys(buildConfigs);
|
|
449
|
+
log(`\u{1F4E6} \u6784\u5EFA\u7B56\u7565: ${strategyNames.join(", ")}`);
|
|
469
450
|
return buildConfigs;
|
|
470
451
|
} catch (error) {
|
|
471
452
|
log("\u751F\u6210\u6784\u5EFA\u914D\u7F6E\u5931\u8D25:", error);
|
|
@@ -475,6 +456,7 @@ function generateBuildConfig(options) {
|
|
|
475
456
|
function generateStrategyConfig(strategyName, pages, entryFiles, strategyConfig, pageConfigs, defaultTemplate, placeholder, log) {
|
|
476
457
|
const htmlInputs = {};
|
|
477
458
|
const tempFiles = [];
|
|
459
|
+
const allPageDefines = {};
|
|
478
460
|
for (const pageName of pages) {
|
|
479
461
|
const entryFile = entryFiles.find((f) => f.name === pageName);
|
|
480
462
|
if (!entryFile)
|
|
@@ -486,6 +468,9 @@ function generateStrategyConfig(strategyName, pages, entryFiles, strategyConfig,
|
|
|
486
468
|
strategy: strategyName
|
|
487
469
|
};
|
|
488
470
|
const pageConfig = getPageConfig(pageConfigs, pageContext, log);
|
|
471
|
+
if (pageConfig == null ? void 0 : pageConfig.define) {
|
|
472
|
+
Object.assign(allPageDefines, pageConfig.define);
|
|
473
|
+
}
|
|
489
474
|
let templatePath = defaultTemplate;
|
|
490
475
|
const pageSpecificTemplate = `${pageName}.html`;
|
|
491
476
|
if (fs2.existsSync(path3.resolve(process.cwd(), pageSpecificTemplate))) {
|
|
@@ -506,21 +491,6 @@ function generateStrategyConfig(strategyName, pages, entryFiles, strategyConfig,
|
|
|
506
491
|
entryPath
|
|
507
492
|
);
|
|
508
493
|
}
|
|
509
|
-
if (pageConfig == null ? void 0 : pageConfig.define) {
|
|
510
|
-
const defineScript = Object.entries(pageConfig.define).map(([key, value]) => {
|
|
511
|
-
const stringValue = typeof value === "string" ? `"${value}"` : JSON.stringify(value);
|
|
512
|
-
return `window.${key} = ${stringValue};`;
|
|
513
|
-
}).join("\n");
|
|
514
|
-
if (defineScript) {
|
|
515
|
-
templateContent = templateContent.replace(
|
|
516
|
-
/<\/head>/i,
|
|
517
|
-
`<script type="text/javascript">
|
|
518
|
-
${defineScript}
|
|
519
|
-
</script>
|
|
520
|
-
</head>`
|
|
521
|
-
);
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
494
|
const tempHtmlPath = path3.resolve(process.cwd(), `.temp.mp.${pageName}.html`);
|
|
525
495
|
fs2.writeFileSync(tempHtmlPath, templateContent);
|
|
526
496
|
tempFiles.push(tempHtmlPath);
|
|
@@ -548,6 +518,12 @@ ${defineScript}
|
|
|
548
518
|
if (strategyConfig) {
|
|
549
519
|
config = mergeConfig(baseConfig, strategyConfig);
|
|
550
520
|
}
|
|
521
|
+
if (Object.keys(allPageDefines).length > 0) {
|
|
522
|
+
config.define = {
|
|
523
|
+
...config.define,
|
|
524
|
+
...allPageDefines
|
|
525
|
+
};
|
|
526
|
+
}
|
|
551
527
|
if (!config.build)
|
|
552
528
|
config.build = {};
|
|
553
529
|
if (!config.build.rollupOptions)
|
|
@@ -604,7 +580,11 @@ function hasCustomConfig() {
|
|
|
604
580
|
async function loadUserConfig(context) {
|
|
605
581
|
const customConfig = await loadCustomConfig();
|
|
606
582
|
if (customConfig) {
|
|
607
|
-
|
|
583
|
+
const result = customConfig(context);
|
|
584
|
+
if (!result) {
|
|
585
|
+
return {};
|
|
586
|
+
}
|
|
587
|
+
return result;
|
|
608
588
|
}
|
|
609
589
|
return null;
|
|
610
590
|
}
|
|
@@ -832,6 +812,7 @@ export {
|
|
|
832
812
|
defineConfigTransform,
|
|
833
813
|
generateBuildConfig,
|
|
834
814
|
getAvailableStrategies,
|
|
815
|
+
mergeWithDefaults,
|
|
835
816
|
viteMultiPage
|
|
836
817
|
};
|
|
837
818
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/dev-server.ts","../src/file-filter.ts","../src/utils.ts","../src/page-config.ts","../src/build-config.ts","../src/config-loader.ts","../src/defaults.ts","../src/types.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport type { Plugin } from 'vite';\nimport { mergeConfig } from 'vite';\nimport { setupDevMiddleware } from './dev-server';\nimport { generateBuildConfig } from './build-config';\nimport { loadUserConfig, hasCustomConfig } from './config-loader';\nimport { mergeWithDefaults } from './defaults';\nimport type { Options, ConfigTransformFunction } from './types';\n\n// 导出类型和工具函数\nexport { defineConfig, defineConfigTransform } from './types';\nexport type {\n ConfigFunction,\n ConfigTransformFunction,\n PluginContext,\n PageContext,\n PageConfig,\n} from './types';\n\nexport function viteMultiPage(transform?: ConfigTransformFunction): Plugin {\n let resolvedOptions: Options;\n const tempFiles: string[] = [];\n let log: (...args: any[]) => void = () => {}; // 默认为空函数\n\n return {\n name: 'vite-multi-page',\n\n async configResolved(config) {\n // 加载用户配置文件(如果存在)\n let userConfig: Options | null = null;\n\n if (hasCustomConfig()) {\n userConfig = await loadUserConfig({\n mode: config.command === 'serve' ? 'development' : 'production',\n command: config.command,\n isCLI: false,\n });\n }\n\n // 合并用户配置和默认配置\n const mergedConfig = mergeWithDefaults(userConfig);\n\n // 应用配置变换函数(如果提供)\n resolvedOptions = transform\n ? transform(mergedConfig, {\n mode: config.command === 'serve' ? 'development' : 'production',\n command: config.command,\n isCLI: false,\n })\n : mergedConfig;\n\n // 设置debug日志\n const debug = resolvedOptions.debug ?? false;\n log = debug ? console.log.bind(console, '[vite-multi-page]') : () => {};\n\n log('Vite配置已解析, 使用配置:', {\n strategies: Object.keys(resolvedOptions.strategies || {}),\n entry: resolvedOptions.entry,\n });\n },\n\n async config(config, { command }) {\n if (command === 'build') {\n // 在config钩子中临时加载配置,因为configResolved还没运行\n if (!resolvedOptions) {\n // 加载用户配置文件(如果存在)\n let userConfig: Options | null = null;\n\n if (hasCustomConfig()) {\n userConfig = await loadUserConfig({\n mode: 'production',\n command: 'build',\n isCLI: false,\n });\n }\n\n // 合并用户配置和默认配置\n const mergedConfig = mergeWithDefaults(userConfig);\n\n // 应用配置变换函数(如果提供)\n resolvedOptions = transform\n ? transform(mergedConfig, {\n mode: 'production',\n command: 'build',\n isCLI: false,\n })\n : mergedConfig;\n const debug = resolvedOptions.debug ?? false;\n log = debug ? console.log.bind(console, '[vite-multi-page]') : () => {};\n }\n\n log('配置构建模式');\n\n // 生成构建配置\n const forceBuildStrategy = process.env.VITE_BUILD_STRATEGY;\n const buildConfigs = generateBuildConfig({\n entry: resolvedOptions.entry || 'src/pages/**/*.{ts,js}',\n exclude: resolvedOptions.exclude || [],\n template: resolvedOptions.template || 'index.html',\n placeholder: resolvedOptions.placeholder || '{{ENTRY_FILE}}',\n strategies: resolvedOptions.strategies || {},\n pageConfigs: resolvedOptions.pageConfigs || {},\n forceBuildStrategy,\n });\n\n // 应用构建配置中的策略(如果有forceBuildStrategy,buildConfigs只会包含该策略)\n const targetStrategy = Object.keys(buildConfigs)[0];\n\n if (targetStrategy && buildConfigs[targetStrategy]) {\n log(`应用构建策略: ${targetStrategy}`);\n const strategyConfig = buildConfigs[targetStrategy];\n\n // 使用Vite的mergeConfig进行智能深度合并\n const mergedConfig = mergeConfig(config, strategyConfig);\n\n // 将合并结果复制回config对象\n Object.assign(config, mergedConfig);\n\n log(`已应用策略 \"${targetStrategy}\" 的配置:`, {\n build: !!strategyConfig.build,\n define: !!strategyConfig.define,\n plugins: strategyConfig.plugins?.length || 0,\n });\n } else {\n log('未找到可用的构建策略,使用默认配置');\n\n throw new Error(\n '❌ 构建失败: 未找到任何构建策略\\n\\n' +\n '可能的原因:\\n' +\n ' 1. 配置文件返回空对象 {}\\n' +\n ' 2. 未找到匹配的入口文件\\n' +\n ' 3. 模板文件不存在\\n' +\n ' 4. 未配置 strategies 对象\\n\\n' +\n '最小配置示例:\\n' +\n 'export default () => ({\\n' +\n ' entry: \"src/pages/**/*.{ts,js}\",\\n' +\n ' template: \"index.html\",\\n' +\n ' strategies: {\\n' +\n ' default: {}\\n' +\n ' }\\n' +\n '});'\n );\n }\n }\n },\n\n configureServer(server) {\n if (server.config.command === 'serve') {\n log('配置开发服务器');\n\n setupDevMiddleware(\n server,\n {\n entry: resolvedOptions.entry || 'src/pages/**/*.{ts,js}',\n exclude: resolvedOptions.exclude || [],\n template: resolvedOptions.template || 'index.html',\n placeholder: resolvedOptions.placeholder || '{{ENTRY_FILE}}',\n strategies: resolvedOptions.strategies || {},\n pageConfigs: resolvedOptions.pageConfigs || {},\n },\n log\n );\n }\n },\n\n buildEnd() {\n // 清理临时文件\n if (tempFiles.length > 0) {\n log(`清理 ${tempFiles.length} 个临时文件`);\n tempFiles.forEach(file => {\n try {\n if (fs.existsSync(file)) {\n fs.unlinkSync(file);\n log(`删除临时文件: ${file}`);\n }\n } catch (error) {\n log(`删除临时文件失败: ${file}`, error);\n }\n });\n tempFiles.length = 0;\n }\n },\n };\n}\n\nexport default viteMultiPage;\nexport type { Options } from './types';\nexport { generateBuildConfig, getAvailableStrategies } from './build-config';\n","import type { ViteDevServer } from 'vite';\nimport * as path from 'node:path';\nimport * as fs from 'node:fs';\nimport { glob } from 'glob';\nimport { filterEntryFiles } from './file-filter';\nimport { escapeRegExp } from './utils';\nimport { DevServerOptions, PageConfigContext } from './types';\nimport { getPageConfig } from './page-config';\n\nexport function configureDevServer(\n server: ViteDevServer,\n options: DevServerOptions,\n log: (...args: any[]) => void\n) {\n try {\n const allFiles = glob.sync(options.entry, { cwd: process.cwd() });\n let entryFiles = filterEntryFiles(allFiles, options.entry, options.exclude, log);\n\n if (entryFiles.length === 0) {\n log('警告: 未找到匹配的入口文件');\n return;\n }\n\n // 获取指定的策略,优先使用命令行参数\n const cliStrategy = ((server.config as any).__cliStrategy ||\n (server.config as any).strategy) as string | undefined;\n\n // 如果指定了策略,则只显示该策略下的页面或没有指定策略的默认页面\n if (cliStrategy) {\n log(`开发服务器使用指定的策略: ${cliStrategy}`);\n\n // 过滤入口文件,只保留匹配策略的页面\n entryFiles = entryFiles.filter(file => {\n const pageName = file.name;\n const pageStrategy = options.appliedStrategies?.get(pageName) || undefined;\n\n // 在指定策略为default时,包含所有没有指定策略的页面\n if (cliStrategy === 'default') {\n return !pageStrategy || pageStrategy === 'default';\n }\n\n // 其他策略,只包含匹配的页面\n return pageStrategy === cliStrategy;\n });\n\n log(`策略 \"${cliStrategy}\" 下可用的页面: ${entryFiles.map(f => f.name).join(', ') || '无'}`);\n }\n\n log('开发服务器应用的入口文件:', entryFiles);\n\n // 修改中间件来处理HTML请求\n server.middlewares.use(async (req, res, next) => {\n try {\n const url = req.url || '';\n const pathWithoutQuery = url.split('?')[0];\n\n // 处理根路径请求 - 显示所有页面的索引\n if (pathWithoutQuery === '/') {\n const indexHtml = generateIndexHtml(entryFiles, options, log);\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/html');\n res.end(indexHtml);\n return;\n }\n\n // 跳过明显的静态资源请求\n if (\n pathWithoutQuery.match(/\\.(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)$/) &&\n !pathWithoutQuery.endsWith('.html')\n ) {\n return next();\n }\n\n // 提取页面名称,同时处理带.html后缀和不带后缀的情况\n let pageName = '';\n if (pathWithoutQuery.endsWith('.html')) {\n pageName = path.basename(pathWithoutQuery, '.html');\n } else if (pathWithoutQuery.startsWith('/')) {\n // 处理无扩展名的路径,如 /mobile\n pageName = pathWithoutQuery.substring(1); // 移除开头的斜杠\n }\n\n if (!pageName) {\n return next();\n }\n\n const matchedFile = entryFiles.find(file => file.name === pageName);\n\n if (!matchedFile) {\n return next();\n }\n\n // 获取页面配置\n const pageContext = {\n pageName: matchedFile.name,\n filePath: matchedFile.file,\n relativePath: path.relative(process.cwd(), matchedFile.file),\n strategy: undefined,\n isMatched: false,\n } as PageConfigContext;\n\n const pageConfig = getPageConfig(options.pageConfigs, pageContext, log);\n\n // 应用配置策略\n if (pageConfig?.strategy) {\n pageContext.strategy = pageConfig.strategy;\n } else if (options.appliedStrategies?.has(pageName)) {\n // 使用缓存的策略信息\n const strategyName = options.appliedStrategies.get(pageName);\n if (strategyName) {\n pageContext.strategy = strategyName;\n }\n }\n\n // 获取模板文件路径\n // 首先检查是否有页面特定的模板(例如mobile.html对应mobile页面)\n let templatePath = '';\n\n // 尝试以页面名称查找匹配的模板\n const pageSpecificTemplate = path.resolve(process.cwd(), `${pageName}.html`);\n if (fs.existsSync(pageSpecificTemplate)) {\n templatePath = pageSpecificTemplate;\n }\n // 然后尝试使用页面配置中指定的模板\n else if (pageConfig?.template) {\n templatePath = path.resolve(process.cwd(), pageConfig.template);\n }\n // 最后使用默认模板\n else {\n templatePath = path.resolve(process.cwd(), options.template);\n }\n\n if (!fs.existsSync(templatePath)) {\n return next();\n }\n\n // 读取并修改模板\n let html = fs.readFileSync(templatePath, 'utf-8');\n\n // 检查模板中是否包含占位符\n const containsPlaceholder = html.includes(options.placeholder);\n\n // 替换占位符为入口文件路径\n if (containsPlaceholder) {\n const originalHtml = html;\n\n // 方式1: 直接字符串替换\n html = html.split(options.placeholder).join(`/${matchedFile.file}`);\n\n // 检查替换结果\n if (html === originalHtml) {\n // 方式2: 正则表达式替换\n const escapedPlaceholder = escapeRegExp(options.placeholder);\n const placeholderRegex = new RegExp(escapedPlaceholder, 'g');\n html = originalHtml.replace(placeholderRegex, `/${matchedFile.file}`);\n\n // 检查替换结果\n if (html === originalHtml) {\n // 方式3: 硬编码替换具体的占位符格式\n html = originalHtml.replace(/\\{\\{ENTRY_FILE\\}\\}/g, `/${matchedFile.file}`);\n }\n }\n }\n\n // 添加页面级define变量\n if (pageConfig?.define) {\n const defineScript = Object.entries(pageConfig.define)\n .map(([key, value]) => {\n const stringValue = typeof value === 'string' ? `\"${value}\"` : JSON.stringify(value);\n return `window.${key} = ${stringValue};`;\n })\n .join('\\n');\n\n if (defineScript) {\n // 注入到head标签底部\n html = html.replace(\n /<\\/head>/i,\n `<script type=\"text/javascript\">\\n${defineScript}\\n</script>\\n</head>`\n );\n }\n }\n\n // 发送响应\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/html');\n res.end(html);\n } catch (error) {\n log(`开发服务器处理请求失败: ${error}`);\n next(error);\n }\n });\n\n log('开发服务器配置完成');\n } catch (error) {\n log(`配置开发服务器失败: ${error}`);\n throw error;\n }\n}\n\n// 为了兼容性,导出setupDevMiddleware作为configureDevServer的别名\nexport const setupDevMiddleware = configureDevServer;\n\n// 生成索引页面HTML\nfunction generateIndexHtml(\n entryFiles: { name: string; file: string }[],\n options: DevServerOptions,\n log: (...args: any[]) => void\n): string {\n try {\n const pageItems = entryFiles\n .map(file => {\n // 获取页面配置和策略\n const pageContext = {\n pageName: file.name,\n filePath: file.file,\n relativePath: path.relative(process.cwd(), file.file),\n strategy: undefined,\n isMatched: false,\n };\n\n const pageConfig = getPageConfig(options.pageConfigs, pageContext, log);\n\n // 确定策略\n let strategy = 'default';\n if (pageConfig?.strategy) {\n strategy = pageConfig.strategy;\n } else if (options.appliedStrategies?.has(file.name)) {\n const strategyName = options.appliedStrategies.get(file.name);\n if (strategyName) {\n strategy = strategyName;\n }\n }\n\n const strategyBadge =\n strategy !== 'default' ? `<span class=\"badge\">${strategy}</span>` : '';\n\n return `\n <div class=\"page-item\">\n <a href=\"${file.name}.html\" class=\"page-link\">\n ${file.name}${strategyBadge}\n </a>\n <div class=\"page-path\">${file.file}</div>\n </div>`;\n })\n .join('');\n\n return `\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>多页面应用索引</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;\n line-height: 1.6;\n color: #333;\n max-width: 1200px;\n margin: 0 auto;\n padding: 20px;\n background-color: #f5f5f7;\n }\n h1 {\n font-size: 24px;\n margin-bottom: 20px;\n color: #111;\n }\n .page-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n }\n .page-item {\n background-color: white;\n border-radius: 8px;\n padding: 16px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.1);\n transition: transform 0.2s, box-shadow 0.2s;\n }\n .page-item:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 8px rgba(0,0,0,0.1);\n }\n .page-link {\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 18px;\n font-weight: 500;\n color: #0066cc;\n text-decoration: none;\n margin-bottom: 8px;\n }\n .page-path {\n font-size: 14px;\n color: #666;\n word-break: break-all;\n }\n .badge {\n display: inline-block;\n font-size: 12px;\n padding: 2px 8px;\n border-radius: 12px;\n background-color: #e6f2ff;\n color: #0066cc;\n margin-left: 8px;\n }\n .stats {\n margin-bottom: 20px;\n font-size: 14px;\n color: #666;\n }\n </style>\n </head>\n <body>\n <h1>多页面应用索引</h1>\n <div class=\"stats\">\n 找到 ${entryFiles.length} 个页面\n </div>\n <div class=\"page-list\">\n ${pageItems}\n </div>\n </body>\n </html>\n `;\n } catch (error) {\n log(`生成索引页失败: ${error}`);\n return `\n <!DOCTYPE html>\n <html>\n <head>\n <title>错误</title>\n </head>\n <body>\n <h1>生成索引页时发生错误</h1>\n <p>${error}</p>\n </body>\n </html>\n `;\n }\n}\n","import * as path from 'node:path';\nimport type { EntryFile, CandidateFile } from './types';\n\nexport function filterEntryFiles(\n files: string[],\n entry: string,\n exclude: string[],\n log: (...args: any[]) => void\n): EntryFile[] {\n const result: EntryFile[] = [];\n const nameToFile = new Map<string, { file: string; priority: number }>();\n\n // 从entry模式中提取基础目录\n let basePattern = entry.replace(/\\/\\*.*$/, ''); // 去掉glob部分\n // 如果基础模式为空或不合理,使用默认处理\n if (!basePattern || basePattern === entry) {\n basePattern = path.dirname(entry.split('*')[0]);\n }\n log('基础目录模式:', basePattern);\n\n const candidateFiles: CandidateFile[] = [];\n\n for (const file of files) {\n if (exclude.includes(file)) {\n log(`跳过排除文件: ${file}`);\n continue;\n }\n\n const relativePath = path.relative(basePattern, file);\n const pathParts = relativePath.split(path.sep);\n\n log(`处理文件: ${file}`);\n log(`相对路径: ${relativePath}`);\n log(`路径部分: ${pathParts}`);\n\n if (pathParts.length === 1) {\n // 第一级文件:src/pages/about.js -> /about.html\n const fileName = pathParts[0];\n const name = path.basename(fileName, path.extname(fileName));\n candidateFiles.push({ name, file, priority: 1 });\n log(`📄 第一级文件: ${file} -> ${name}.html (优先级: 1)`);\n } else if (pathParts.length >= 2) {\n // 目录下的文件\n const fileName = path.basename(file, path.extname(file));\n const dirName = pathParts[0];\n\n if (fileName === 'main') {\n // 目录下的main文件:src/pages/mobile/main.ts -> /mobile.html\n candidateFiles.push({ name: dirName, file, priority: 2 });\n log(`📁 目录main文件: ${file} -> ${dirName}.html (优先级: 2)`);\n } else {\n log(`❌ 跳过文件: ${file} (不是main文件)`);\n }\n } else {\n log(`❌ 跳过文件: ${file} (路径层级不符合)`);\n }\n }\n\n // 按照优先级处理冲突:目录优先覆盖文件(优先级2 > 优先级1)\n for (const candidate of candidateFiles) {\n const existing = nameToFile.get(candidate.name);\n\n if (!existing) {\n nameToFile.set(candidate.name, { file: candidate.file, priority: candidate.priority });\n log(`✅ 添加页面: ${candidate.name} -> ${candidate.file}`);\n } else {\n if (candidate.priority > existing.priority) {\n nameToFile.set(candidate.name, { file: candidate.file, priority: candidate.priority });\n log(\n `🔄 替换页面: ${candidate.name} -> ${candidate.file} (替换 ${existing.file}, 目录优先)`\n );\n } else {\n log(`⚠️ 冲突跳过: ${candidate.name} -> ${candidate.file} (保留 ${existing.file})`);\n }\n }\n }\n\n for (const [name, { file }] of nameToFile.entries()) {\n result.push({ name, file });\n }\n\n return result;\n}\n","export function escapeRegExp(string: string): string {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function createLogger(debug: boolean) {\n return (...args: any[]) => {\n if (debug) {\n console.log('[vite-plugin-multi-page]', ...args);\n }\n };\n}\n","import type { PageConfig, PageConfigFunction, PageConfigContext } from './types';\n\n/**\n * 根据页面上下文获取页面配置\n */\nexport function getPageConfig(\n pageConfigs: Record<string, PageConfig> | PageConfigFunction | undefined,\n context: PageConfigContext,\n log: (...args: any[]) => void\n): PageConfig | null {\n if (!pageConfigs) return null;\n\n // 如果是函数,直接调用\n if (typeof pageConfigs === 'function') {\n const result = pageConfigs(context);\n if (result) {\n log(`函数配置匹配页面 ${context.pageName}:`, result);\n }\n return result;\n }\n\n // 对象配置:支持精确匹配和模式匹配\n for (const [key, config] of Object.entries(pageConfigs)) {\n // 精确匹配页面名称\n if (key === context.pageName) {\n log(`精确匹配页面 ${context.pageName}:`, config);\n return config;\n }\n\n // 模式匹配\n if (config.match) {\n const patterns = Array.isArray(config.match) ? config.match : [config.match];\n const isMatched = patterns.some(\n pattern =>\n simpleMatch(pattern, context.pageName) ||\n simpleMatch(pattern, context.relativePath) ||\n simpleMatch(pattern, context.filePath)\n );\n\n if (isMatched) {\n log(`模式匹配页面 ${context.pageName} (模式: ${config.match}):`, config);\n return { ...config, match: undefined };\n }\n }\n\n // glob 模式匹配页面名称\n if (simpleMatch(key, context.pageName)) {\n log(`Glob匹配页面 ${context.pageName} (模式: ${key}):`, config);\n return config;\n }\n }\n\n return null;\n}\n\n/**\n * 简单的模式匹配函数\n */\nfunction simpleMatch(pattern: string, text: string): boolean {\n const regexPattern = pattern\n .replace(/\\*\\*/g, '__DOUBLE_STAR__')\n .replace(/\\*/g, '[^/]*')\n .replace(/__DOUBLE_STAR__/g, '.*');\n const regex = new RegExp(`^${regexPattern}$`);\n return regex.test(text);\n}\n","import type { UserConfig } from 'vite';\nimport { mergeConfig } from 'vite';\nimport { glob } from 'glob';\nimport * as path from 'node:path';\nimport * as fs from 'node:fs';\nimport { filterEntryFiles } from './file-filter';\nimport { getPageConfig } from './page-config';\nimport type { BuildConfigOptions, PageConfigContext, ConfigStrategy } from './types';\nimport { createLogger } from './utils';\n\n/**\n * 构建时配置生成器\n * 根据策略和页面配置生成多页面构建配置\n */\nexport function generateBuildConfig(options: BuildConfigOptions): Record<string, UserConfig> {\n const {\n entry = 'src/pages/*/main.{ts,js}',\n exclude = [],\n template = 'index.html',\n placeholder = '<!--VITE_MULTI_PAGE_ENTRY-->',\n strategies = {},\n pageConfigs = {},\n forceBuildStrategy,\n } = options;\n\n const log = createLogger(true);\n const buildConfigs: Record<string, UserConfig> = {};\n\n try {\n // 1. 发现所有页面入口文件\n const allFiles = glob.sync(entry, { cwd: process.cwd() });\n const entryFiles = filterEntryFiles(allFiles, entry, exclude, log);\n\n if (entryFiles.length === 0) {\n log('警告: 未找到匹配的入口文件');\n return {};\n }\n\n log(`发现 ${entryFiles.length} 个页面入口`);\n\n // 2. 为每个页面分析配置和策略\n const pageStrategies = new Map<string, string>();\n const strategyPages = new Map<string, string[]>();\n\n for (const entryFile of entryFiles) {\n const pageContext = {\n pageName: entryFile.name,\n filePath: entryFile.file,\n relativePath: path.relative(process.cwd(), entryFile.file),\n } as PageConfigContext;\n\n // 获取页面配置\n const pageConfig = getPageConfig(pageConfigs, pageContext, log);\n const strategyName = pageConfig?.strategy || 'default';\n\n pageStrategies.set(entryFile.name, strategyName);\n\n if (!strategyPages.has(strategyName)) {\n strategyPages.set(strategyName, []);\n }\n strategyPages.get(strategyName)?.push(entryFile.name);\n }\n\n log('页面策略分布:', Object.fromEntries(pageStrategies));\n\n // 3. 如果指定了强制策略,只构建该策略的页面\n if (forceBuildStrategy) {\n const targetPages = strategyPages.get(forceBuildStrategy) || [];\n if (targetPages.length === 0) {\n log(`警告: 策略 \"${forceBuildStrategy}\" 下没有页面`);\n return {};\n }\n\n log(`强制构建策略: ${forceBuildStrategy}, 页面: ${targetPages.join(', ')}`);\n\n const config = generateStrategyConfig(\n forceBuildStrategy,\n targetPages,\n entryFiles,\n strategies[forceBuildStrategy],\n pageConfigs,\n template,\n placeholder,\n log\n );\n\n buildConfigs[forceBuildStrategy] = config;\n return buildConfigs;\n }\n\n // 4. 为每个策略生成构建配置\n for (const [strategyName, pages] of strategyPages) {\n if (pages.length === 0) continue;\n\n log(`生成策略 \"${strategyName}\" 的构建配置, 页面: ${pages.join(', ')}`);\n\n // 获取策略配置,如果没有定义则使用空配置(允许默认策略)\n const strategyConfig = strategies[strategyName] || {};\n const config = generateStrategyConfig(\n strategyName,\n pages,\n entryFiles,\n strategyConfig,\n pageConfigs,\n template,\n placeholder,\n log\n );\n\n buildConfigs[strategyName] = config;\n }\n\n // 确保至少有一个构建配置\n if (Object.keys(buildConfigs).length === 0) {\n log('警告: 未生成任何构建配置,创建默认配置');\n\n // 如果没有任何策略,创建一个默认策略包含所有页面\n const allPageNames = entryFiles.map(f => f.name);\n const defaultConfig = generateStrategyConfig(\n 'default',\n allPageNames,\n entryFiles,\n {},\n pageConfigs,\n template,\n placeholder,\n log\n );\n\n buildConfigs['default'] = defaultConfig;\n }\n\n log(`生成了 ${Object.keys(buildConfigs).length} 个构建配置`);\n return buildConfigs;\n } catch (error) {\n log('生成构建配置失败:', error);\n throw error;\n }\n}\n\n/**\n * 为特定策略生成构建配置\n */\nfunction generateStrategyConfig(\n strategyName: string,\n pages: string[],\n entryFiles: Array<{ name: string; file: string }>,\n strategyConfig: ConfigStrategy | undefined,\n pageConfigs: any,\n defaultTemplate: string,\n placeholder: string,\n log: (...args: any[]) => void\n): UserConfig {\n const htmlInputs: Record<string, string> = {};\n const tempFiles: string[] = [];\n\n // 为每个页面确定使用的HTML模板并创建临时文件\n for (const pageName of pages) {\n const entryFile = entryFiles.find(f => f.name === pageName);\n if (!entryFile) continue;\n\n // 获取页面配置\n const pageContext = {\n pageName,\n filePath: entryFile.file,\n relativePath: path.relative(process.cwd(), entryFile.file),\n strategy: strategyName,\n } as PageConfigContext;\n\n const pageConfig = getPageConfig(pageConfigs, pageContext, log);\n\n // 确定HTML模板\n let templatePath = defaultTemplate;\n\n // 1. 页面特定模板(如 mobile.html 对应 mobile 页面)\n const pageSpecificTemplate = `${pageName}.html`;\n if (fs.existsSync(path.resolve(process.cwd(), pageSpecificTemplate))) {\n templatePath = pageSpecificTemplate;\n }\n // 2. 页面配置中指定的模板\n else if (pageConfig?.template) {\n templatePath = pageConfig.template;\n }\n\n // 读取模板内容\n const templateFullPath = path.resolve(process.cwd(), templatePath);\n if (!fs.existsSync(templateFullPath)) {\n log(`警告: 模板文件不存在: ${templatePath}`);\n continue;\n }\n\n let templateContent = fs.readFileSync(templateFullPath, 'utf-8');\n\n // 替换占位符\n if (templateContent.includes(placeholder)) {\n // 临时HTML在项目根目录中,使用相对路径\n const entryPath = `./${entryFile.file}`;\n templateContent = templateContent.replace(\n new RegExp(placeholder.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'g'),\n entryPath\n );\n }\n\n // 添加页面级define变量\n if (pageConfig?.define) {\n const defineScript = Object.entries(pageConfig.define)\n .map(([key, value]) => {\n const stringValue = typeof value === 'string' ? `\"${value}\"` : JSON.stringify(value);\n return `window.${key} = ${stringValue};`;\n })\n .join('\\n');\n\n if (defineScript) {\n templateContent = templateContent.replace(\n /<\\/head>/i,\n `<script type=\"text/javascript\">\\n${defineScript}\\n</script>\\n</head>`\n );\n }\n }\n\n // 创建临时HTML文件,使用新的命名规则:.temp.mp.[name].html\n const tempHtmlPath = path.resolve(process.cwd(), `.temp.mp.${pageName}.html`);\n fs.writeFileSync(tempHtmlPath, templateContent);\n tempFiles.push(tempHtmlPath);\n\n htmlInputs[pageName] = tempHtmlPath;\n }\n\n // 构建基础配置\n const baseConfig: UserConfig = {\n build: {\n rollupOptions: {\n input: htmlInputs, // 使用临时HTML文件作为输入\n output: {\n entryFileNames: 'assets/[name]-[hash].js',\n chunkFileNames: 'assets/[name]-[hash].js',\n assetFileNames: 'assets/[name]-[hash][extname]',\n },\n },\n outDir: `dist/${strategyName}`, // 直接输出到策略目录\n emptyOutDir: false, // 不清空输出目录,避免删除临时HTML文件\n },\n define: {},\n };\n\n // 使用Vite的mergeConfig进行智能深度合并\n let config: UserConfig = baseConfig;\n\n if (strategyConfig) {\n config = mergeConfig(baseConfig, strategyConfig);\n }\n\n // 手动处理需要特殊控制的配置项,防止被mergeConfig覆盖\n if (!config.build) config.build = {};\n if (!config.build.rollupOptions) config.build.rollupOptions = {};\n\n // 确保关键配置不被覆盖\n config.build.outDir = `dist/${strategyName}`; // 强制设置正确的输出目录\n config.build.rollupOptions.input = htmlInputs; // 强制使用临时HTML文件作为输入\n config.build.emptyOutDir = false; // 不清空输出目录,避免删除临时HTML文件\n\n // 简化日志输出\n log(`策略 \"${strategyName}\" - ${pages.length} 个页面`);\n\n return config;\n}\n\n/**\n * 获取所有可用的构建策略\n */\nexport function getAvailableStrategies(options: BuildConfigOptions): string[] {\n const { entry = 'src/pages/*/main.{ts,js}', exclude = [], pageConfigs = {} } = options;\n\n const log = createLogger(false); // 静默模式\n const strategySet = new Set<string>();\n\n try {\n // 发现所有页面入口文件\n const allFiles = glob.sync(entry, { cwd: process.cwd() });\n const entryFiles = filterEntryFiles(allFiles, entry, exclude, log);\n\n // 分析每个页面的策略\n for (const entryFile of entryFiles) {\n const pageContext = {\n pageName: entryFile.name,\n filePath: entryFile.file,\n relativePath: path.relative(process.cwd(), entryFile.file),\n } as PageConfigContext;\n\n const pageConfig = getPageConfig(pageConfigs, pageContext, log);\n const strategyName = pageConfig?.strategy || 'default';\n strategySet.add(strategyName);\n }\n\n // 只返回实际有页面的策略,不添加空策略\n return Array.from(strategySet).sort();\n } catch (error) {\n log('获取可用策略失败:', error);\n return ['default'];\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { Module } from 'node:module';\nimport type { Options } from './types';\n\n/**\n * 配置上下文\n */\nexport interface ConfigContext {\n mode: 'development' | 'production';\n command: 'serve' | 'build';\n isCLI?: boolean;\n}\n\n/**\n * 配置函数类型\n */\nexport type ConfigFunction = (context: ConfigContext) => Options;\n\n/**\n * 配置文件名列表(优先级从高到低)\n */\nconst CONFIG_FILES = [\n 'multipage.config.js',\n 'multipage.config.mjs',\n 'multipage.config.ts',\n] as const;\n\n/**\n * 检查是否存在自定义配置文件\n */\nexport function hasCustomConfig(): boolean {\n for (const filename of CONFIG_FILES) {\n const configPath = path.resolve(process.cwd(), filename);\n if (fs.existsSync(configPath)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * 加载用户的多页面配置\n */\nexport async function loadUserConfig(context: ConfigContext): Promise<Options | null> {\n // 尝试加载项目自定义配置\n const customConfig = await loadCustomConfig();\n\n if (customConfig) {\n // 使用项目自定义配置\n return customConfig(context);\n }\n\n // 没有找到用户配置\n return null;\n}\n\n/**\n * 加载配置文件\n */\nasync function loadConfigFile(filePath: string): Promise<any> {\n // 处理 TypeScript 文件\n if (filePath.endsWith('.ts')) {\n try {\n const code = await fs.promises.readFile(filePath, 'utf-8');\n\n // 使用 esbuild 实时转译 TS → JS\n const esbuild = (await import('esbuild')) as any;\n const result = await esbuild.transform(code, {\n loader: 'ts',\n format: 'cjs', // 使用 CommonJS 格式便于使用 Module._compile\n target: 'node16',\n sourcemap: false,\n });\n\n // 创建临时模块并编译\n const tempModule = new Module(filePath);\n tempModule.filename = filePath;\n tempModule.paths = (Module as any)._nodeModulePaths(path.dirname(filePath));\n\n // 编译代码\n (tempModule as any)._compile(result.code, filePath);\n\n return tempModule.exports;\n } catch (esbuildError) {\n console.warn('esbuild 转译失败,尝试简单转换:', esbuildError);\n\n // 备选方案:简单的文本替换\n const code = await fs.promises.readFile(filePath, 'utf-8');\n const jsCode = code\n .replace(/export\\s+default\\s+/, 'module.exports = ')\n .replace(/import\\s+.*?from\\s+['\"][^'\"]*['\"];?\\s*/g, '')\n .replace(/:\\s*[^=,})\\]]+/g, ''); // 简单的类型注解移除\n\n const tempModule = new Module(filePath);\n tempModule.filename = filePath;\n tempModule.paths = (Module as any)._nodeModulePaths(path.dirname(filePath));\n\n (tempModule as any)._compile(jsCode, filePath);\n return tempModule.exports;\n }\n }\n\n // 处理 JavaScript 文件\n if (filePath.endsWith('.js') || filePath.endsWith('.mjs')) {\n const fileUrl = pathToFileURL(filePath).href;\n return import(`${fileUrl}?t=${Date.now()}`);\n }\n\n throw new Error(`不支持的配置文件类型: ${filePath}`);\n}\n\n/**\n * 加载项目自定义配置文件\n */\nasync function loadCustomConfig(): Promise<ConfigFunction | null> {\n const cwd = process.cwd();\n\n for (const configFile of CONFIG_FILES) {\n const configPath = path.resolve(cwd, configFile);\n\n if (fs.existsSync(configPath)) {\n try {\n const configModule = await loadConfigFile(configPath);\n const configFunction = configModule.default || configModule;\n\n if (typeof configFunction === 'function') {\n return configFunction;\n } else {\n console.warn(`配置文件 ${configFile} 必须默认导出一个函数`);\n }\n } catch (error) {\n if (configFile.endsWith('.ts')) {\n console.error(`加载TypeScript配置文件 ${configFile} 失败:`, error);\n console.log('提示:确保你的项目支持TypeScript,或者使用 .js/.mjs 配置文件');\n } else {\n console.error(`加载配置文件 ${configFile} 失败:`, error);\n }\n }\n }\n }\n\n return null;\n}\n","import type { MultiPageOptions } from './types';\n\n/**\n * 默认配置选项\n */\nexport const DEFAULT_CONFIG: Required<Omit<MultiPageOptions, '__forceBuildStrategy'>> = {\n entry: 'src/pages/**/*.{ts,js}',\n exclude: [],\n template: 'index.html',\n placeholder: '{{ENTRY_FILE}}',\n debug: false,\n strategies: {\n default: {},\n },\n pageConfigs: {},\n};\n\n/**\n * 合并用户配置和默认配置\n */\nexport function mergeWithDefaults(userConfig: MultiPageOptions | null): MultiPageOptions {\n if (!userConfig) {\n return { ...DEFAULT_CONFIG };\n }\n\n return {\n entry: userConfig.entry ?? DEFAULT_CONFIG.entry,\n exclude: userConfig.exclude ?? DEFAULT_CONFIG.exclude,\n template: userConfig.template ?? DEFAULT_CONFIG.template,\n placeholder: userConfig.placeholder ?? DEFAULT_CONFIG.placeholder,\n debug: userConfig.debug ?? DEFAULT_CONFIG.debug,\n strategies: userConfig.strategies ?? DEFAULT_CONFIG.strategies,\n pageConfigs: userConfig.pageConfigs ?? DEFAULT_CONFIG.pageConfigs,\n __forceBuildStrategy: userConfig.__forceBuildStrategy,\n };\n}\n\n/**\n * 检查配置是否为空或无效\n */\nexport function isEmptyConfig(config: MultiPageOptions): boolean {\n // 检查是否是完全空的对象\n if (Object.keys(config).length === 0) {\n return true;\n }\n\n // 检查是否只有默认值或无效值\n const hasValidEntry = config.entry && config.entry !== DEFAULT_CONFIG.entry;\n const hasValidStrategies = config.strategies && Object.keys(config.strategies).length > 0;\n const hasValidPageConfigs =\n config.pageConfigs &&\n (typeof config.pageConfigs === 'function' || Object.keys(config.pageConfigs).length > 0);\n\n return !hasValidEntry && !hasValidStrategies && !hasValidPageConfigs;\n}\n","import type { UserConfig } from 'vite';\n\n// 核心配置选项\nexport interface MultiPageOptions {\n entry?: string;\n exclude?: string[];\n template?: string;\n placeholder?: string;\n debug?: boolean;\n strategies?: Record<string, ConfigStrategy>;\n pageConfigs?: Record<string, PageConfig> | PageConfigFunction;\n __forceBuildStrategy?: string;\n}\n\n// 主要导出类型\nexport type Options = MultiPageOptions;\n\n// 开发服务器选项\nexport interface DevServerOptions {\n entry: string;\n exclude: string[];\n template: string;\n placeholder: string;\n strategies?: Record<string, ConfigStrategy>;\n pageConfigs?: Record<string, PageConfig> | PageConfigFunction;\n appliedStrategies?: Map<string, string>;\n}\n\n// 构建配置选项\nexport interface BuildConfigOptions {\n entry: string;\n exclude: string[];\n template: string;\n placeholder: string;\n strategies?: Record<string, ConfigStrategy>;\n pageConfigs?: Record<string, PageConfig> | PageConfigFunction;\n forceBuildStrategy?: string;\n}\n\n// 策略配置\nexport interface ConfigStrategy extends Omit<UserConfig, 'plugins'> {}\n\n// 页面配置\nexport interface PageConfig {\n strategy?: string;\n define?: Record<string, any>;\n template?: string;\n viteConfig?: UserConfig;\n match?: string;\n}\n\n// 页面上下文\nexport interface PageContext {\n pageName: string;\n filePath: string;\n relativePath: string;\n fullPath?: string;\n strategy?: string;\n isMatched?: boolean;\n}\n\n// 页面配置上下文(别名)\nexport type PageConfigContext = PageContext;\n\n// 页面配置函数\nexport type PageConfigFunction = (context: PageContext) => PageConfig | null;\n\n// 入口文件信息\nexport interface EntryFile {\n name: string;\n file: string;\n}\n\n// 候选文件信息\nexport interface CandidateFile extends EntryFile {\n priority: number;\n}\n\n// 构建策略配置\nexport interface BuildStrategyConfig {\n strategy: string;\n pages: string[];\n configPath?: string;\n}\n\n// CLI选项\nexport interface CLIOptions {\n configFile: string;\n outDir?: string;\n debug?: boolean;\n mode?: string;\n minify?: boolean | string;\n build?: Record<string, any>;\n base?: string;\n strategy?: string;\n port?: number | string;\n host?: string;\n https?: boolean;\n open?: boolean;\n}\n\n// 插件上下文\nexport interface PluginContext {\n mode: string;\n command: 'build' | 'serve';\n isCLI: boolean;\n}\n\n// 配置函数类型\nexport type ConfigFunction = (context: PluginContext) => MultiPageOptions;\n\n// 配置变换函数类型\nexport type ConfigTransformFunction = (\n config: MultiPageOptions,\n context: PluginContext\n) => MultiPageOptions;\n\n// 工具函数:定义配置\nexport function defineConfig(config: MultiPageOptions | ConfigFunction): ConfigFunction {\n // 如果传入的是函数,直接返回\n if (typeof config === 'function') {\n return config;\n }\n\n // 如果传入的是对象,包装成函数返回\n return () => config;\n}\n\n// 工具函数:定义配置变换\nexport function defineConfigTransform(transform: ConfigTransformFunction): ConfigTransformFunction {\n return transform;\n}\n"],"mappings":"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","names":["fs","mergeConfig","path","glob","path","fs","glob","fs","path","mergeConfig"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/dev-server.ts","../src/file-filter.ts","../src/utils.ts","../src/page-config.ts","../src/build-config.ts","../src/config-loader.ts","../src/defaults.ts","../src/types.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport type { Plugin } from 'vite';\nimport { mergeConfig } from 'vite';\nimport { setupDevMiddleware } from './dev-server';\nimport { generateBuildConfig } from './build-config';\nimport { loadUserConfig, hasCustomConfig } from './config-loader';\nimport { mergeWithDefaults } from './defaults';\nimport type { Options, ConfigTransformFunction } from './types';\n\n// 导出类型和工具函数\nexport { defineConfig, defineConfigTransform } from './types';\nexport type {\n ConfigFunction,\n ConfigTransformFunction,\n PluginContext,\n PageContext,\n PageConfig,\n} from './types';\n\nexport function viteMultiPage(transform?: ConfigTransformFunction): Plugin {\n let resolvedOptions: Options;\n const tempFiles: string[] = [];\n let log: (...args: any[]) => void = () => {}; // 默认为空函数\n\n return {\n name: 'vite-multi-page',\n\n async configResolved(config) {\n // 加载用户配置文件(如果存在)\n let userConfig: Options | null = null;\n\n if (hasCustomConfig()) {\n userConfig = await loadUserConfig({\n mode: config.command === 'serve' ? 'development' : 'production',\n command: config.command,\n isCLI: false,\n });\n }\n\n // 合并用户配置和默认配置\n const mergedConfig = mergeWithDefaults(userConfig);\n\n // 应用配置变换函数(如果提供)\n resolvedOptions = transform\n ? transform(mergedConfig, {\n mode: config.command === 'serve' ? 'development' : 'production',\n command: config.command,\n isCLI: false,\n })\n : mergedConfig;\n\n // 设置debug日志\n const debug = resolvedOptions.debug ?? false;\n log = debug ? console.log.bind(console, '[vite-multi-page]') : () => {};\n\n log('Vite配置已解析, 使用配置:', {\n strategies: Object.keys(resolvedOptions.strategies || {}),\n entry: resolvedOptions.entry,\n });\n },\n\n async config(config, { command }) {\n if (command === 'build') {\n // 在config钩子中临时加载配置,因为configResolved还没运行\n if (!resolvedOptions) {\n // 加载用户配置文件(如果存在)\n let userConfig: Options | null = null;\n\n if (hasCustomConfig()) {\n userConfig = await loadUserConfig({\n mode: 'production',\n command: 'build',\n isCLI: false,\n });\n }\n\n // 合并用户配置和默认配置\n const mergedConfig = mergeWithDefaults(userConfig);\n\n // 应用配置变换函数(如果提供)\n resolvedOptions = transform\n ? transform(mergedConfig, {\n mode: 'production',\n command: 'build',\n isCLI: false,\n })\n : mergedConfig;\n const debug = resolvedOptions.debug ?? false;\n log = debug ? console.log.bind(console, '[vite-multi-page]') : () => {};\n }\n\n log('配置构建模式');\n\n // 生成构建配置\n const forceBuildStrategy = process.env.VITE_BUILD_STRATEGY;\n const buildConfigs = generateBuildConfig({\n entry: resolvedOptions.entry || 'src/pages/**/*.{ts,js}',\n exclude: resolvedOptions.exclude || [],\n template: resolvedOptions.template || 'index.html',\n placeholder: resolvedOptions.placeholder || '{{ENTRY_FILE}}',\n strategies: resolvedOptions.strategies || {},\n pageConfigs: resolvedOptions.pageConfigs || {},\n forceBuildStrategy,\n });\n\n // 应用构建配置中的策略(如果有forceBuildStrategy,buildConfigs只会包含该策略)\n const targetStrategy = Object.keys(buildConfigs)[0];\n\n if (targetStrategy && buildConfigs[targetStrategy]) {\n log(`应用构建策略: ${targetStrategy}`);\n const strategyConfig = buildConfigs[targetStrategy];\n\n // 使用Vite的mergeConfig进行智能深度合并\n const mergedConfig = mergeConfig(config, strategyConfig);\n\n // 将合并结果复制回config对象\n Object.assign(config, mergedConfig);\n\n log(`已应用策略 \"${targetStrategy}\" 的配置:`, {\n build: !!strategyConfig.build,\n define: !!strategyConfig.define,\n plugins: strategyConfig.plugins?.length || 0,\n });\n } else {\n log('未找到可用的构建策略,使用默认配置');\n\n throw new Error(\n '❌ 构建失败: 未找到任何构建策略\\n\\n' +\n '可能的原因:\\n' +\n ' 1. 配置文件返回空对象 {}\\n' +\n ' 2. 未找到匹配的入口文件\\n' +\n ' 3. 模板文件不存在\\n' +\n ' 4. 未配置 strategies 对象\\n\\n' +\n '最小配置示例:\\n' +\n 'export default () => ({\\n' +\n ' entry: \"src/pages/**/*.{ts,js}\",\\n' +\n ' template: \"index.html\",\\n' +\n ' strategies: {\\n' +\n ' default: {}\\n' +\n ' }\\n' +\n '});'\n );\n }\n }\n },\n\n configureServer(server) {\n if (server.config.command === 'serve') {\n log('配置开发服务器');\n\n setupDevMiddleware(\n server,\n {\n entry: resolvedOptions.entry || 'src/pages/**/*.{ts,js}',\n exclude: resolvedOptions.exclude || [],\n template: resolvedOptions.template || 'index.html',\n placeholder: resolvedOptions.placeholder || '{{ENTRY_FILE}}',\n strategies: resolvedOptions.strategies || {},\n pageConfigs: resolvedOptions.pageConfigs || {},\n },\n log\n );\n }\n },\n\n buildEnd() {\n // 清理临时文件\n if (tempFiles.length > 0) {\n log(`清理 ${tempFiles.length} 个临时文件`);\n tempFiles.forEach(file => {\n try {\n if (fs.existsSync(file)) {\n fs.unlinkSync(file);\n log(`删除临时文件: ${file}`);\n }\n } catch (error) {\n log(`删除临时文件失败: ${file}`, error);\n }\n });\n tempFiles.length = 0;\n }\n },\n };\n}\n\nexport default viteMultiPage;\nexport type { Options } from './types';\nexport { generateBuildConfig, getAvailableStrategies } from './build-config';\nexport { mergeWithDefaults } from './defaults';\n","import type { ViteDevServer } from 'vite';\nimport * as path from 'node:path';\nimport * as fs from 'node:fs';\nimport { glob } from 'glob';\nimport { filterEntryFiles } from './file-filter';\nimport { escapeRegExp } from './utils';\nimport { DevServerOptions, PageConfigContext } from './types';\nimport { getPageConfig } from './page-config';\n\nexport function configureDevServer(\n server: ViteDevServer,\n options: DevServerOptions,\n log: (...args: any[]) => void\n) {\n try {\n const allFiles = glob.sync(options.entry, { cwd: process.cwd() });\n let entryFiles = filterEntryFiles(allFiles, options.entry, options.exclude, log);\n\n if (entryFiles.length === 0) {\n log('警告: 未找到匹配的入口文件');\n return;\n }\n\n // 获取指定的策略,优先使用命令行参数\n const cliStrategy = ((server.config as any).__cliStrategy ||\n (server.config as any).strategy) as string | undefined;\n\n // 如果指定了策略,则只显示该策略下的页面或没有指定策略的默认页面\n if (cliStrategy) {\n log(`开发服务器使用指定的策略: ${cliStrategy}`);\n\n // 过滤入口文件,只保留匹配策略的页面\n entryFiles = entryFiles.filter(file => {\n const pageName = file.name;\n const pageStrategy = options.appliedStrategies?.get(pageName) || undefined;\n\n // 在指定策略为default时,包含所有没有指定策略的页面\n if (cliStrategy === 'default') {\n return !pageStrategy || pageStrategy === 'default';\n }\n\n // 其他策略,只包含匹配的页面\n return pageStrategy === cliStrategy;\n });\n\n log(`策略 \"${cliStrategy}\" 下可用的页面: ${entryFiles.map(f => f.name).join(', ') || '无'}`);\n }\n\n log('开发服务器应用的入口文件:', entryFiles);\n\n // 修改中间件来处理HTML请求\n server.middlewares.use(async (req, res, next) => {\n try {\n const url = req.url || '';\n const pathWithoutQuery = url.split('?')[0];\n\n // 处理根路径请求 - 显示所有页面的索引\n if (pathWithoutQuery === '/') {\n const indexHtml = generateIndexHtml(entryFiles, options, log);\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/html');\n res.end(indexHtml);\n return;\n }\n\n // 跳过明显的静态资源请求\n if (\n pathWithoutQuery.match(/\\.(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)$/) &&\n !pathWithoutQuery.endsWith('.html')\n ) {\n return next();\n }\n\n // 提取页面名称,同时处理带.html后缀和不带后缀的情况\n let pageName = '';\n if (pathWithoutQuery.endsWith('.html')) {\n pageName = path.basename(pathWithoutQuery, '.html');\n } else if (pathWithoutQuery.startsWith('/')) {\n // 处理无扩展名的路径,如 /mobile\n pageName = pathWithoutQuery.substring(1); // 移除开头的斜杠\n }\n\n if (!pageName) {\n return next();\n }\n\n const matchedFile = entryFiles.find(file => file.name === pageName);\n\n if (!matchedFile) {\n return next();\n }\n\n // 获取页面配置\n const pageContext = {\n pageName: matchedFile.name,\n filePath: matchedFile.file,\n relativePath: path.relative(process.cwd(), matchedFile.file),\n strategy: undefined,\n isMatched: false,\n } as PageConfigContext;\n\n const pageConfig = getPageConfig(options.pageConfigs, pageContext, log);\n\n // 应用配置策略\n if (pageConfig?.strategy) {\n pageContext.strategy = pageConfig.strategy;\n } else if (options.appliedStrategies?.has(pageName)) {\n // 使用缓存的策略信息\n const strategyName = options.appliedStrategies.get(pageName);\n if (strategyName) {\n pageContext.strategy = strategyName;\n }\n }\n\n // 获取模板文件路径\n // 首先检查是否有页面特定的模板(例如mobile.html对应mobile页面)\n let templatePath = '';\n\n // 尝试以页面名称查找匹配的模板\n const pageSpecificTemplate = path.resolve(process.cwd(), `${pageName}.html`);\n if (fs.existsSync(pageSpecificTemplate)) {\n templatePath = pageSpecificTemplate;\n }\n // 然后尝试使用页面配置中指定的模板\n else if (pageConfig?.template) {\n templatePath = path.resolve(process.cwd(), pageConfig.template);\n }\n // 最后使用默认模板\n else {\n templatePath = path.resolve(process.cwd(), options.template);\n }\n\n if (!fs.existsSync(templatePath)) {\n return next();\n }\n\n // 读取并修改模板\n let html = fs.readFileSync(templatePath, 'utf-8');\n\n // 检查模板中是否包含占位符\n const containsPlaceholder = html.includes(options.placeholder);\n\n // 替换占位符为入口文件路径\n if (containsPlaceholder) {\n const originalHtml = html;\n\n // 方式1: 直接字符串替换\n html = html.split(options.placeholder).join(`/${matchedFile.file}`);\n\n // 检查替换结果\n if (html === originalHtml) {\n // 方式2: 正则表达式替换\n const escapedPlaceholder = escapeRegExp(options.placeholder);\n const placeholderRegex = new RegExp(escapedPlaceholder, 'g');\n html = originalHtml.replace(placeholderRegex, `/${matchedFile.file}`);\n\n // 检查替换结果\n if (html === originalHtml) {\n // 方式3: 硬编码替换具体的占位符格式\n html = originalHtml.replace(/\\{\\{ENTRY_FILE\\}\\}/g, `/${matchedFile.file}`);\n }\n }\n }\n\n // 添加页面级define变量\n if (pageConfig?.define) {\n const defineScript = Object.entries(pageConfig.define)\n .map(([key, value]) => {\n const stringValue = typeof value === 'string' ? `\"${value}\"` : JSON.stringify(value);\n return `window.${key} = ${stringValue};`;\n })\n .join('\\n');\n\n if (defineScript) {\n // 注入到head标签底部\n html = html.replace(\n /<\\/head>/i,\n `<script type=\"text/javascript\">\\n${defineScript}\\n</script>\\n</head>`\n );\n }\n }\n\n // 发送响应\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/html');\n res.end(html);\n } catch (error) {\n log(`开发服务器处理请求失败: ${error}`);\n next(error);\n }\n });\n\n log('开发服务器配置完成');\n } catch (error) {\n log(`配置开发服务器失败: ${error}`);\n throw error;\n }\n}\n\n// 为了兼容性,导出setupDevMiddleware作为configureDevServer的别名\nexport const setupDevMiddleware = configureDevServer;\n\n// 生成索引页面HTML\nfunction generateIndexHtml(\n entryFiles: { name: string; file: string }[],\n options: DevServerOptions,\n log: (...args: any[]) => void\n): string {\n try {\n const pageItems = entryFiles\n .map(file => {\n // 获取页面配置和策略\n const pageContext = {\n pageName: file.name,\n filePath: file.file,\n relativePath: path.relative(process.cwd(), file.file),\n strategy: undefined,\n isMatched: false,\n };\n\n const pageConfig = getPageConfig(options.pageConfigs, pageContext, log);\n\n // 确定策略\n let strategy = 'default';\n if (pageConfig?.strategy) {\n strategy = pageConfig.strategy;\n } else if (options.appliedStrategies?.has(file.name)) {\n const strategyName = options.appliedStrategies.get(file.name);\n if (strategyName) {\n strategy = strategyName;\n }\n }\n\n const strategyBadge =\n strategy !== 'default' ? `<span class=\"badge\">${strategy}</span>` : '';\n\n return `\n <div class=\"page-item\">\n <a href=\"${file.name}.html\" class=\"page-link\">\n ${file.name}${strategyBadge}\n </a>\n <div class=\"page-path\">${file.file}</div>\n </div>`;\n })\n .join('');\n\n return `\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>多页面应用索引</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;\n line-height: 1.6;\n color: #333;\n max-width: 1200px;\n margin: 0 auto;\n padding: 20px;\n background-color: #f5f5f7;\n }\n h1 {\n font-size: 24px;\n margin-bottom: 20px;\n color: #111;\n }\n .page-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n }\n .page-item {\n background-color: white;\n border-radius: 8px;\n padding: 16px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.1);\n transition: transform 0.2s, box-shadow 0.2s;\n }\n .page-item:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 8px rgba(0,0,0,0.1);\n }\n .page-link {\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 18px;\n font-weight: 500;\n color: #0066cc;\n text-decoration: none;\n margin-bottom: 8px;\n }\n .page-path {\n font-size: 14px;\n color: #666;\n word-break: break-all;\n }\n .badge {\n display: inline-block;\n font-size: 12px;\n padding: 2px 8px;\n border-radius: 12px;\n background-color: #e6f2ff;\n color: #0066cc;\n margin-left: 8px;\n }\n .stats {\n margin-bottom: 20px;\n font-size: 14px;\n color: #666;\n }\n </style>\n </head>\n <body>\n <h1>多页面应用索引</h1>\n <div class=\"stats\">\n 找到 ${entryFiles.length} 个页面\n </div>\n <div class=\"page-list\">\n ${pageItems}\n </div>\n </body>\n </html>\n `;\n } catch (error) {\n log(`生成索引页失败: ${error}`);\n return `\n <!DOCTYPE html>\n <html>\n <head>\n <title>错误</title>\n </head>\n <body>\n <h1>生成索引页时发生错误</h1>\n <p>${error}</p>\n </body>\n </html>\n `;\n }\n}\n","import * as path from 'node:path';\nimport type { EntryFile, CandidateFile } from './types';\n\nexport function filterEntryFiles(\n files: string[],\n entry: string,\n exclude: string[],\n _log: (...args: any[]) => void\n): EntryFile[] {\n const result: EntryFile[] = [];\n const nameToFile = new Map<string, { file: string; priority: number }>();\n\n // 从entry模式中提取基础目录\n let basePattern = entry.replace(/\\/\\*.*$/, ''); // 去掉glob部分\n // 如果基础模式为空或不合理,使用默认处理\n if (!basePattern || basePattern === entry) {\n basePattern = path.dirname(entry.split('*')[0]);\n }\n const candidateFiles: CandidateFile[] = [];\n\n for (const file of files) {\n if (exclude.includes(file)) {\n continue;\n }\n\n const relativePath = path.relative(basePattern, file);\n const pathParts = relativePath.split(path.sep);\n\n if (pathParts.length === 1) {\n // 第一级文件:src/pages/about.js -> /about.html\n const fileName = pathParts[0];\n const name = path.basename(fileName, path.extname(fileName));\n candidateFiles.push({ name, file, priority: 1 });\n } else if (pathParts.length >= 2) {\n // 目录下的文件\n const fileName = path.basename(file, path.extname(file));\n const dirName = pathParts[0];\n\n if (fileName === 'main') {\n // 目录下的main文件:src/pages/mobile/main.ts -> /mobile.html\n candidateFiles.push({ name: dirName, file, priority: 2 });\n }\n }\n }\n\n // 按照优先级处理冲突:目录优先覆盖文件(优先级2 > 优先级1)\n for (const candidate of candidateFiles) {\n const existing = nameToFile.get(candidate.name);\n\n if (!existing) {\n nameToFile.set(candidate.name, { file: candidate.file, priority: candidate.priority });\n } else {\n if (candidate.priority > existing.priority) {\n nameToFile.set(candidate.name, { file: candidate.file, priority: candidate.priority });\n }\n }\n }\n\n for (const [name, { file }] of nameToFile.entries()) {\n result.push({ name, file });\n }\n\n return result;\n}\n","export function escapeRegExp(string: string): string {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function createLogger(debug: boolean) {\n return (...args: any[]) => {\n if (debug) {\n console.log('[vite-plugin-multi-page]', ...args);\n }\n };\n}\n","import type { PageConfig, PageConfigFunction, PageConfigContext } from './types';\n\n/**\n * 根据页面上下文获取页面配置\n */\nexport function getPageConfig(\n pageConfigs: Record<string, PageConfig> | PageConfigFunction | undefined,\n context: PageConfigContext,\n log: (...args: any[]) => void\n): PageConfig | null {\n if (!pageConfigs) return null;\n\n // 如果是函数,直接调用\n if (typeof pageConfigs === 'function') {\n const result = pageConfigs(context);\n if (result) {\n // log(`函数配置匹配页面 ${context.pageName}:`, result);\n }\n return result;\n }\n\n // 对象配置:支持精确匹配和模式匹配\n for (const [key, config] of Object.entries(pageConfigs)) {\n // 精确匹配页面名称\n if (key === context.pageName) {\n log(`精确匹配页面 ${context.pageName}:`, config);\n return config;\n }\n\n // 模式匹配\n if (config.match) {\n const patterns = Array.isArray(config.match) ? config.match : [config.match];\n const isMatched = patterns.some(\n pattern =>\n simpleMatch(pattern, context.pageName) ||\n simpleMatch(pattern, context.relativePath) ||\n simpleMatch(pattern, context.filePath)\n );\n\n if (isMatched) {\n log(`模式匹配页面 ${context.pageName} (模式: ${config.match}):`, config);\n return { ...config, match: undefined };\n }\n }\n\n // glob 模式匹配页面名称\n if (simpleMatch(key, context.pageName)) {\n log(`Glob匹配页面 ${context.pageName} (模式: ${key}):`, config);\n return config;\n }\n }\n\n return null;\n}\n\n/**\n * 简单的模式匹配函数\n */\nfunction simpleMatch(pattern: string, text: string): boolean {\n const regexPattern = pattern\n .replace(/\\*\\*/g, '__DOUBLE_STAR__')\n .replace(/\\*/g, '[^/]*')\n .replace(/__DOUBLE_STAR__/g, '.*');\n const regex = new RegExp(`^${regexPattern}$`);\n return regex.test(text);\n}\n","import type { UserConfig } from 'vite';\nimport { mergeConfig } from 'vite';\nimport { glob } from 'glob';\nimport * as path from 'node:path';\nimport * as fs from 'node:fs';\nimport { filterEntryFiles } from './file-filter';\nimport { getPageConfig } from './page-config';\nimport type { BuildConfigOptions, PageConfigContext, ConfigStrategy } from './types';\nimport { createLogger } from './utils';\n\n/**\n * 构建时配置生成器\n * 根据策略和页面配置生成多页面构建配置\n */\nexport function generateBuildConfig(options: BuildConfigOptions): Record<string, UserConfig> {\n const {\n entry = 'src/pages/*/main.{ts,js}',\n exclude = [],\n template = 'index.html',\n placeholder = '<!--VITE_MULTI_PAGE_ENTRY-->',\n strategies = {},\n pageConfigs = {},\n forceBuildStrategy,\n } = options;\n\n const log = createLogger(true);\n const buildConfigs: Record<string, UserConfig> = {};\n\n try {\n // 1. 发现所有页面入口文件\n const allFiles = glob.sync(entry, { cwd: process.cwd() });\n const entryFiles = filterEntryFiles(allFiles, entry, exclude, log);\n\n if (entryFiles.length === 0) {\n log('警告: 未找到匹配的入口文件');\n return {};\n }\n\n // 2. 为每个页面分析配置和策略\n const pageStrategies = new Map<string, string>();\n const strategyPages = new Map<string, string[]>();\n\n for (const entryFile of entryFiles) {\n const pageContext = {\n pageName: entryFile.name,\n filePath: entryFile.file,\n relativePath: path.relative(process.cwd(), entryFile.file),\n } as PageConfigContext;\n\n // 获取页面配置\n const pageConfig = getPageConfig(pageConfigs, pageContext, log);\n const strategyName = pageConfig?.strategy || 'default';\n\n pageStrategies.set(entryFile.name, strategyName);\n\n if (!strategyPages.has(strategyName)) {\n strategyPages.set(strategyName, []);\n }\n strategyPages.get(strategyName)?.push(entryFile.name);\n }\n\n log(`📄 发现 ${entryFiles.length} 个页面: ${entryFiles.map(f => f.name).join(', ')}`);\n\n // 3. 如果指定了强制策略,只构建该策略的页面\n if (forceBuildStrategy) {\n const targetPages = strategyPages.get(forceBuildStrategy) || [];\n if (targetPages.length === 0) {\n log(`警告: 策略 \"${forceBuildStrategy}\" 下没有页面`);\n return {};\n }\n\n log(`强制构建策略: ${forceBuildStrategy}, 页面: ${targetPages.join(', ')}`);\n\n const config = generateStrategyConfig(\n forceBuildStrategy,\n targetPages,\n entryFiles,\n strategies[forceBuildStrategy],\n pageConfigs,\n template,\n placeholder,\n log\n );\n\n buildConfigs[forceBuildStrategy] = config;\n return buildConfigs;\n }\n\n // 4. 为每个策略生成构建配置\n for (const [strategyName, pages] of strategyPages) {\n if (pages.length === 0) continue;\n\n // 获取策略配置,如果没有定义则使用空配置(允许默认策略)\n const strategyConfig = strategies[strategyName] || {};\n const config = generateStrategyConfig(\n strategyName,\n pages,\n entryFiles,\n strategyConfig,\n pageConfigs,\n template,\n placeholder,\n log\n );\n\n buildConfigs[strategyName] = config;\n }\n\n // 确保至少有一个构建配置\n if (Object.keys(buildConfigs).length === 0) {\n log('警告: 未生成任何构建配置,创建默认配置');\n\n // 如果没有任何策略,创建一个默认策略包含所有页面\n const allPageNames = entryFiles.map(f => f.name);\n const defaultConfig = generateStrategyConfig(\n 'default',\n allPageNames,\n entryFiles,\n {},\n pageConfigs,\n template,\n placeholder,\n log\n );\n\n buildConfigs['default'] = defaultConfig;\n }\n\n const strategyNames = Object.keys(buildConfigs);\n log(`📦 构建策略: ${strategyNames.join(', ')}`);\n return buildConfigs;\n } catch (error) {\n log('生成构建配置失败:', error);\n throw error;\n }\n}\n\n/**\n * 为特定策略生成构建配置\n */\nfunction generateStrategyConfig(\n strategyName: string,\n pages: string[],\n entryFiles: Array<{ name: string; file: string }>,\n strategyConfig: ConfigStrategy | undefined,\n pageConfigs: any,\n defaultTemplate: string,\n placeholder: string,\n log: (...args: any[]) => void\n): UserConfig {\n const htmlInputs: Record<string, string> = {};\n const tempFiles: string[] = [];\n\n // 收集所有页面的 define 变量\n const allPageDefines: Record<string, any> = {};\n\n // 为每个页面确定使用的HTML模板并创建临时文件\n for (const pageName of pages) {\n const entryFile = entryFiles.find(f => f.name === pageName);\n if (!entryFile) continue;\n\n // 获取页面配置\n const pageContext = {\n pageName,\n filePath: entryFile.file,\n relativePath: path.relative(process.cwd(), entryFile.file),\n strategy: strategyName,\n } as PageConfigContext;\n\n const pageConfig = getPageConfig(pageConfigs, pageContext, log);\n\n // 收集页面级 define 变量\n if (pageConfig?.define) {\n Object.assign(allPageDefines, pageConfig.define);\n }\n\n // 确定HTML模板\n let templatePath = defaultTemplate;\n\n // 1. 页面特定模板(如 mobile.html 对应 mobile 页面)\n const pageSpecificTemplate = `${pageName}.html`;\n if (fs.existsSync(path.resolve(process.cwd(), pageSpecificTemplate))) {\n templatePath = pageSpecificTemplate;\n }\n // 2. 页面配置中指定的模板\n else if (pageConfig?.template) {\n templatePath = pageConfig.template;\n }\n\n // 读取模板内容\n const templateFullPath = path.resolve(process.cwd(), templatePath);\n if (!fs.existsSync(templateFullPath)) {\n log(`警告: 模板文件不存在: ${templatePath}`);\n continue;\n }\n\n let templateContent = fs.readFileSync(templateFullPath, 'utf-8');\n\n // 替换占位符\n if (templateContent.includes(placeholder)) {\n // 临时HTML在项目根目录中,使用相对路径\n const entryPath = `./${entryFile.file}`;\n templateContent = templateContent.replace(\n new RegExp(placeholder.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'g'),\n entryPath\n );\n }\n\n // 创建临时HTML文件,使用新的命名规则:.temp.mp.[name].html\n const tempHtmlPath = path.resolve(process.cwd(), `.temp.mp.${pageName}.html`);\n fs.writeFileSync(tempHtmlPath, templateContent);\n tempFiles.push(tempHtmlPath);\n\n htmlInputs[pageName] = tempHtmlPath;\n }\n\n // 构建基础配置\n const baseConfig: UserConfig = {\n build: {\n rollupOptions: {\n input: htmlInputs, // 使用临时HTML文件作为输入\n output: {\n entryFileNames: 'assets/[name]-[hash].js',\n chunkFileNames: 'assets/[name]-[hash].js',\n assetFileNames: 'assets/[name]-[hash][extname]',\n },\n },\n outDir: `dist/${strategyName}`, // 直接输出到策略目录\n emptyOutDir: false, // 不清空输出目录,避免删除临时HTML文件\n },\n define: {},\n };\n\n // 使用Vite的mergeConfig进行智能深度合并\n let config: UserConfig = baseConfig;\n\n if (strategyConfig) {\n config = mergeConfig(baseConfig, strategyConfig);\n }\n\n // 合并页面级 define 变量到 Vite 的 define 配置中\n // 页面级 define 优先级高于策略级 define\n if (Object.keys(allPageDefines).length > 0) {\n config.define = {\n ...config.define,\n ...allPageDefines,\n };\n }\n\n // 手动处理需要特殊控制的配置项,防止被mergeConfig覆盖\n if (!config.build) config.build = {};\n if (!config.build.rollupOptions) config.build.rollupOptions = {};\n\n // 确保关键配置不被覆盖\n config.build.outDir = `dist/${strategyName}`; // 强制设置正确的输出目录\n config.build.rollupOptions.input = htmlInputs; // 强制使用临时HTML文件作为输入\n config.build.emptyOutDir = false; // 不清空输出目录,避免删除临时HTML文件\n\n // 简化日志输出\n log(`策略 \"${strategyName}\" - ${pages.length} 个页面`);\n\n return config;\n}\n\n/**\n * 获取所有可用的构建策略\n */\nexport function getAvailableStrategies(options: BuildConfigOptions): string[] {\n const { entry = 'src/pages/*/main.{ts,js}', exclude = [], pageConfigs = {} } = options;\n\n const log = createLogger(false); // 静默模式\n const strategySet = new Set<string>();\n\n try {\n // 发现所有页面入口文件\n const allFiles = glob.sync(entry, { cwd: process.cwd() });\n const entryFiles = filterEntryFiles(allFiles, entry, exclude, log);\n\n // 分析每个页面的策略\n for (const entryFile of entryFiles) {\n const pageContext = {\n pageName: entryFile.name,\n filePath: entryFile.file,\n relativePath: path.relative(process.cwd(), entryFile.file),\n } as PageConfigContext;\n\n const pageConfig = getPageConfig(pageConfigs, pageContext, log);\n const strategyName = pageConfig?.strategy || 'default';\n strategySet.add(strategyName);\n }\n\n // 只返回实际有页面的策略,不添加空策略\n return Array.from(strategySet).sort();\n } catch (error) {\n log('获取可用策略失败:', error);\n return ['default'];\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { Module } from 'node:module';\nimport type { Options } from './types';\n\n/**\n * 配置上下文\n */\nexport interface ConfigContext {\n mode: 'development' | 'production';\n command: 'serve' | 'build';\n isCLI?: boolean;\n}\n\n/**\n * 配置函数类型\n */\nexport type ConfigFunction = (context: ConfigContext) => Options;\n\n/**\n * 配置文件名列表(优先级从高到低)\n */\nconst CONFIG_FILES = [\n 'multipage.config.js',\n 'multipage.config.mjs',\n 'multipage.config.ts',\n] as const;\n\n/**\n * 检查是否存在自定义配置文件\n */\nexport function hasCustomConfig(): boolean {\n for (const filename of CONFIG_FILES) {\n const configPath = path.resolve(process.cwd(), filename);\n if (fs.existsSync(configPath)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * 加载用户的多页面配置\n */\nexport async function loadUserConfig(context: ConfigContext): Promise<Options | null> {\n // 尝试加载项目自定义配置\n const customConfig = await loadCustomConfig();\n\n if (customConfig) {\n // 使用项目自定义配置\n const result = customConfig(context);\n\n // 如果配置函数返回 undefined 或 null,视为空配置\n if (!result) {\n return {};\n }\n\n return result;\n }\n\n // 没有找到用户配置\n return null;\n}\n\n/**\n * 加载配置文件\n */\nasync function loadConfigFile(filePath: string): Promise<any> {\n // 处理 TypeScript 文件\n if (filePath.endsWith('.ts')) {\n try {\n const code = await fs.promises.readFile(filePath, 'utf-8');\n\n // 使用 esbuild 实时转译 TS → JS\n const esbuild = (await import('esbuild')) as any;\n const result = await esbuild.transform(code, {\n loader: 'ts',\n format: 'cjs', // 使用 CommonJS 格式便于使用 Module._compile\n target: 'node16',\n sourcemap: false,\n });\n\n // 创建临时模块并编译\n const tempModule = new Module(filePath);\n tempModule.filename = filePath;\n tempModule.paths = (Module as any)._nodeModulePaths(path.dirname(filePath));\n\n // 编译代码\n (tempModule as any)._compile(result.code, filePath);\n\n return tempModule.exports;\n } catch (esbuildError) {\n console.warn('esbuild 转译失败,尝试简单转换:', esbuildError);\n\n // 备选方案:简单的文本替换\n const code = await fs.promises.readFile(filePath, 'utf-8');\n const jsCode = code\n .replace(/export\\s+default\\s+/, 'module.exports = ')\n .replace(/import\\s+.*?from\\s+['\"][^'\"]*['\"];?\\s*/g, '')\n .replace(/:\\s*[^=,})\\]]+/g, ''); // 简单的类型注解移除\n\n const tempModule = new Module(filePath);\n tempModule.filename = filePath;\n tempModule.paths = (Module as any)._nodeModulePaths(path.dirname(filePath));\n\n (tempModule as any)._compile(jsCode, filePath);\n return tempModule.exports;\n }\n }\n\n // 处理 JavaScript 文件\n if (filePath.endsWith('.js') || filePath.endsWith('.mjs')) {\n const fileUrl = pathToFileURL(filePath).href;\n return import(`${fileUrl}?t=${Date.now()}`);\n }\n\n throw new Error(`不支持的配置文件类型: ${filePath}`);\n}\n\n/**\n * 加载项目自定义配置文件\n */\nasync function loadCustomConfig(): Promise<ConfigFunction | null> {\n const cwd = process.cwd();\n\n for (const configFile of CONFIG_FILES) {\n const configPath = path.resolve(cwd, configFile);\n\n if (fs.existsSync(configPath)) {\n try {\n const configModule = await loadConfigFile(configPath);\n const configFunction = configModule.default || configModule;\n\n if (typeof configFunction === 'function') {\n return configFunction;\n } else {\n console.warn(`配置文件 ${configFile} 必须默认导出一个函数`);\n }\n } catch (error) {\n if (configFile.endsWith('.ts')) {\n console.error(`加载TypeScript配置文件 ${configFile} 失败:`, error);\n console.log('提示:确保你的项目支持TypeScript,或者使用 .js/.mjs 配置文件');\n } else {\n console.error(`加载配置文件 ${configFile} 失败:`, error);\n }\n }\n }\n }\n\n return null;\n}\n","import type { MultiPageOptions } from './types';\n\n/**\n * 默认配置选项\n */\nexport const DEFAULT_CONFIG: Required<Omit<MultiPageOptions, '__forceBuildStrategy'>> = {\n entry: 'src/pages/**/*.{ts,js}',\n exclude: [],\n template: 'index.html',\n placeholder: '{{ENTRY_FILE}}',\n debug: false,\n strategies: {\n default: {},\n },\n pageConfigs: {},\n};\n\n/**\n * 合并用户配置和默认配置\n */\nexport function mergeWithDefaults(\n userConfig: MultiPageOptions | null | undefined\n): MultiPageOptions {\n if (!userConfig) {\n return { ...DEFAULT_CONFIG };\n }\n\n return {\n entry: userConfig.entry ?? DEFAULT_CONFIG.entry,\n exclude: userConfig.exclude ?? DEFAULT_CONFIG.exclude,\n template: userConfig.template ?? DEFAULT_CONFIG.template,\n placeholder: userConfig.placeholder ?? DEFAULT_CONFIG.placeholder,\n debug: userConfig.debug ?? DEFAULT_CONFIG.debug,\n strategies: userConfig.strategies ?? DEFAULT_CONFIG.strategies,\n pageConfigs: userConfig.pageConfigs ?? DEFAULT_CONFIG.pageConfigs,\n __forceBuildStrategy: userConfig.__forceBuildStrategy,\n };\n}\n\n/**\n * 检查配置是否为空或无效\n */\nexport function isEmptyConfig(config: MultiPageOptions): boolean {\n // 检查是否是完全空的对象\n if (Object.keys(config).length === 0) {\n return true;\n }\n\n // 检查是否只有默认值或无效值\n const hasValidEntry = config.entry && config.entry !== DEFAULT_CONFIG.entry;\n const hasValidStrategies = config.strategies && Object.keys(config.strategies).length > 0;\n const hasValidPageConfigs =\n config.pageConfigs &&\n (typeof config.pageConfigs === 'function' || Object.keys(config.pageConfigs).length > 0);\n\n return !hasValidEntry && !hasValidStrategies && !hasValidPageConfigs;\n}\n","import type { UserConfig } from 'vite';\n\n// 核心配置选项\nexport interface MultiPageOptions {\n entry?: string;\n exclude?: string[];\n template?: string;\n placeholder?: string;\n debug?: boolean;\n strategies?: Record<string, ConfigStrategy>;\n pageConfigs?: Record<string, PageConfig> | PageConfigFunction;\n __forceBuildStrategy?: string;\n}\n\n// 主要导出类型\nexport type Options = MultiPageOptions;\n\n// 开发服务器选项\nexport interface DevServerOptions {\n entry: string;\n exclude: string[];\n template: string;\n placeholder: string;\n strategies?: Record<string, ConfigStrategy>;\n pageConfigs?: Record<string, PageConfig> | PageConfigFunction;\n appliedStrategies?: Map<string, string>;\n}\n\n// 构建配置选项\nexport interface BuildConfigOptions {\n entry: string;\n exclude: string[];\n template: string;\n placeholder: string;\n strategies?: Record<string, ConfigStrategy>;\n pageConfigs?: Record<string, PageConfig> | PageConfigFunction;\n forceBuildStrategy?: string;\n}\n\n// 策略配置\nexport interface ConfigStrategy extends Omit<UserConfig, 'plugins'> {}\n\n// 页面配置\nexport interface PageConfig {\n strategy?: string;\n define?: Record<string, any>;\n template?: string;\n viteConfig?: UserConfig;\n match?: string;\n}\n\n// 页面上下文\nexport interface PageContext {\n pageName: string;\n filePath: string;\n relativePath: string;\n fullPath?: string;\n strategy?: string;\n isMatched?: boolean;\n}\n\n// 页面配置上下文(别名)\nexport type PageConfigContext = PageContext;\n\n// 页面配置函数\nexport type PageConfigFunction = (context: PageContext) => PageConfig | null;\n\n// 入口文件信息\nexport interface EntryFile {\n name: string;\n file: string;\n}\n\n// 候选文件信息\nexport interface CandidateFile extends EntryFile {\n priority: number;\n}\n\n// 构建策略配置\nexport interface BuildStrategyConfig {\n strategy: string;\n pages: string[];\n configPath?: string;\n}\n\n// CLI选项\nexport interface CLIOptions {\n configFile: string;\n outDir?: string;\n debug?: boolean;\n mode?: string;\n minify?: boolean | string;\n build?: Record<string, any>;\n base?: string;\n strategy?: string;\n port?: number | string;\n host?: string;\n https?: boolean;\n open?: boolean;\n}\n\n// 插件上下文\nexport interface PluginContext {\n mode: string;\n command: 'build' | 'serve';\n isCLI: boolean;\n}\n\n// 配置函数类型\nexport type ConfigFunction = (context: PluginContext) => MultiPageOptions;\n\n// 配置变换函数类型\nexport type ConfigTransformFunction = (\n config: MultiPageOptions,\n context: PluginContext\n) => MultiPageOptions;\n\n// 工具函数:定义配置\nexport function defineConfig(config: MultiPageOptions | ConfigFunction): ConfigFunction {\n // 如果传入的是函数,直接返回\n if (typeof config === 'function') {\n return config;\n }\n\n // 如果传入的是对象,包装成函数返回\n return () => config;\n}\n\n// 工具函数:定义配置变换\nexport function defineConfigTransform(transform: ConfigTransformFunction): ConfigTransformFunction {\n return transform;\n}\n"],"mappings":"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","names":["fs","mergeConfig","path","glob","path","fs","glob","fs","path","mergeConfig"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fchc8/vite-plugin-multi-page",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "A powerful Vite plugin for building multi-page applications with smart file routing and multi-strategy builds",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"build": "tsup",
|
|
39
|
+
"postbuild": "rm -f dist/index.d.mts",
|
|
39
40
|
"dev": "tsup --watch",
|
|
40
41
|
"type-check": "tsc --noEmit",
|
|
41
42
|
"lint": "eslint src --ext .ts --fix",
|