@fchc8/vite-plugin-multi-page 1.0.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/LICENSE +21 -0
- package/README-EN.md +424 -0
- package/README.md +502 -0
- package/dist/index.d.mts +89 -0
- package/dist/index.d.ts +89 -0
- package/dist/index.js +441 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +406 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +88 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import * as path4 from "node:path";
|
|
3
|
+
import * as fs3 from "node:fs";
|
|
4
|
+
|
|
5
|
+
// src/utils.ts
|
|
6
|
+
function escapeRegExp(string) {
|
|
7
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8
|
+
}
|
|
9
|
+
function createLogger(debug) {
|
|
10
|
+
return (...args) => {
|
|
11
|
+
if (debug) {
|
|
12
|
+
console.log("[vite-plugin-multi-page]", ...args);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// src/dev-server.ts
|
|
18
|
+
import * as path2 from "node:path";
|
|
19
|
+
import * as fs from "node:fs";
|
|
20
|
+
import { glob } from "glob";
|
|
21
|
+
|
|
22
|
+
// src/file-filter.ts
|
|
23
|
+
import * as path from "node:path";
|
|
24
|
+
function filterEntryFiles(files, entry, exclude, log) {
|
|
25
|
+
const result = [];
|
|
26
|
+
const nameToFile = /* @__PURE__ */ new Map();
|
|
27
|
+
const basePattern = entry.replace(/\/\*\*.*$/, "");
|
|
28
|
+
log("\u57FA\u7840\u76EE\u5F55\u6A21\u5F0F:", basePattern);
|
|
29
|
+
const candidateFiles = [];
|
|
30
|
+
for (const file of files) {
|
|
31
|
+
if (exclude.includes(file)) {
|
|
32
|
+
log(`\u8DF3\u8FC7\u6392\u9664\u6587\u4EF6: ${file}`);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const relativePath = path.relative(basePattern, file);
|
|
36
|
+
const pathParts = relativePath.split(path.sep);
|
|
37
|
+
log(`\u5904\u7406\u6587\u4EF6: ${file}`);
|
|
38
|
+
log(`\u76F8\u5BF9\u8DEF\u5F84: ${relativePath}`);
|
|
39
|
+
log(`\u8DEF\u5F84\u90E8\u5206: ${pathParts}`);
|
|
40
|
+
if (pathParts.length === 1) {
|
|
41
|
+
const fileName = pathParts[0];
|
|
42
|
+
const name = path.basename(fileName, path.extname(fileName));
|
|
43
|
+
candidateFiles.push({ name, file, priority: 1 });
|
|
44
|
+
log(`\u{1F4C4} \u7B2C\u4E00\u7EA7\u6587\u4EF6: ${file} -> ${name}.html (\u4F18\u5148\u7EA7: 1)`);
|
|
45
|
+
} else if (pathParts.length >= 2) {
|
|
46
|
+
const fileName = path.basename(file, path.extname(file));
|
|
47
|
+
const dirName = pathParts[0];
|
|
48
|
+
if (fileName === "main") {
|
|
49
|
+
candidateFiles.push({ name: dirName, file, priority: 2 });
|
|
50
|
+
log(`\u{1F4C1} \u76EE\u5F55main\u6587\u4EF6: ${file} -> ${dirName}.html (\u4F18\u5148\u7EA7: 2)`);
|
|
51
|
+
} else {
|
|
52
|
+
log(`\u274C \u8DF3\u8FC7\u6587\u4EF6: ${file} (\u4E0D\u662Fmain\u6587\u4EF6)`);
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
log(`\u274C \u8DF3\u8FC7\u6587\u4EF6: ${file} (\u8DEF\u5F84\u5C42\u7EA7\u4E0D\u7B26\u5408)`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
for (const candidate of candidateFiles) {
|
|
59
|
+
const existing = nameToFile.get(candidate.name);
|
|
60
|
+
if (!existing) {
|
|
61
|
+
nameToFile.set(candidate.name, candidate.file);
|
|
62
|
+
log(`\u2705 \u6DFB\u52A0\u9875\u9762: ${candidate.name} -> ${candidate.file}`);
|
|
63
|
+
} else {
|
|
64
|
+
const existingCandidate = candidateFiles.find((c) => c.file === existing);
|
|
65
|
+
if (existingCandidate && candidate.priority > existingCandidate.priority) {
|
|
66
|
+
nameToFile.set(candidate.name, candidate.file);
|
|
67
|
+
log(`\u{1F504} \u66FF\u6362\u9875\u9762: ${candidate.name} -> ${candidate.file} (\u66FF\u6362 ${existing})`);
|
|
68
|
+
} else {
|
|
69
|
+
log(`\u26A0\uFE0F \u51B2\u7A81\u8DF3\u8FC7: ${candidate.name} -> ${candidate.file} (\u4FDD\u7559 ${existing})`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
for (const [name, file] of nameToFile.entries()) {
|
|
74
|
+
result.push({ name, file });
|
|
75
|
+
}
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// src/dev-server.ts
|
|
80
|
+
function configureDevServer(server, options, log) {
|
|
81
|
+
const allFiles = glob.sync(options.entry, { cwd: process.cwd() });
|
|
82
|
+
const entryFiles = filterEntryFiles(allFiles, options.entry, options.exclude, log);
|
|
83
|
+
const pageMap = /* @__PURE__ */ new Map();
|
|
84
|
+
entryFiles.forEach(({ name, file }) => {
|
|
85
|
+
pageMap.set(name, file);
|
|
86
|
+
});
|
|
87
|
+
const pageNames = Array.from(pageMap.keys());
|
|
88
|
+
log("Available pages:", pageNames);
|
|
89
|
+
log("Page mapping:", Object.fromEntries(pageMap));
|
|
90
|
+
server.middlewares.use((req, res, next) => {
|
|
91
|
+
var _a;
|
|
92
|
+
const originalUrl = req.url;
|
|
93
|
+
const url = originalUrl == null ? void 0 : originalUrl.split("?")[0];
|
|
94
|
+
if (!url) {
|
|
95
|
+
return next();
|
|
96
|
+
}
|
|
97
|
+
log(`\u5904\u7406\u8BF7\u6C42: ${url}`);
|
|
98
|
+
if (url === "/" && pageNames.length > 0) {
|
|
99
|
+
const defaultPage = pageNames.includes("index") ? "index" : pageNames[0];
|
|
100
|
+
log(`\u6839\u8DEF\u5F84\u91CD\u5B9A\u5411\u5230: ${defaultPage}`);
|
|
101
|
+
req.url = `/${defaultPage}.html`;
|
|
102
|
+
}
|
|
103
|
+
const finalUrl = (_a = req.url) == null ? void 0 : _a.split("?")[0];
|
|
104
|
+
const pageMatch = finalUrl == null ? void 0 : finalUrl.match(/^\/([^\/\.]+)(\.html)?$/);
|
|
105
|
+
if (pageMatch) {
|
|
106
|
+
const pageName = pageMatch[1];
|
|
107
|
+
log(`\u5339\u914D\u5230\u9875\u9762: ${pageName}`);
|
|
108
|
+
log(`\u53EF\u7528\u9875\u9762\u5217\u8868: ${pageNames.join(", ")}`);
|
|
109
|
+
if (pageMap.has(pageName)) {
|
|
110
|
+
const relativeEntryPath = pageMap.get(pageName);
|
|
111
|
+
const entryPath = path2.resolve(process.cwd(), relativeEntryPath);
|
|
112
|
+
log(`\u9875\u9762 ${pageName} \u5BF9\u5E94\u6587\u4EF6: ${relativeEntryPath}`);
|
|
113
|
+
if (fs.existsSync(entryPath)) {
|
|
114
|
+
log(`\u627E\u5230\u5165\u53E3\u6587\u4EF6: ${entryPath}`);
|
|
115
|
+
const templatePath = path2.resolve(process.cwd(), options.template);
|
|
116
|
+
if (fs.existsSync(templatePath)) {
|
|
117
|
+
let html = fs.readFileSync(templatePath, "utf-8");
|
|
118
|
+
log(`\u8BFB\u53D6\u6A21\u677F\u6587\u4EF6: ${templatePath}`);
|
|
119
|
+
log(`\u6A21\u677F\u5185\u5BB9\u5305\u542B\u5360\u4F4D\u7B26: ${html.includes(options.placeholder)}`);
|
|
120
|
+
if (!html.includes(options.placeholder)) {
|
|
121
|
+
console.warn(
|
|
122
|
+
`[vite-plugin-multi-page] \u6A21\u677F\u6587\u4EF6\u4E2D\u6CA1\u6709\u627E\u5230\u5360\u4F4D\u7B26: ${options.placeholder}`
|
|
123
|
+
);
|
|
124
|
+
return next();
|
|
125
|
+
}
|
|
126
|
+
const entryFile = `/${relativeEntryPath}`;
|
|
127
|
+
html = html.replace(new RegExp(escapeRegExp(options.placeholder), "g"), entryFile);
|
|
128
|
+
log(`\u5360\u4F4D\u7B26 ${options.placeholder} \u66FF\u6362\u4E3A: ${entryFile}`);
|
|
129
|
+
log(`\u66FF\u6362\u540E\u5305\u542B\u5360\u4F4D\u7B26: ${html.includes(options.placeholder)}`);
|
|
130
|
+
res.setHeader("Content-Type", "text/html");
|
|
131
|
+
res.end(html);
|
|
132
|
+
return;
|
|
133
|
+
} else {
|
|
134
|
+
log(`\u6A21\u677F\u6587\u4EF6\u4E0D\u5B58\u5728: ${templatePath}`);
|
|
135
|
+
}
|
|
136
|
+
} else {
|
|
137
|
+
log(`\u5165\u53E3\u6587\u4EF6\u4E0D\u5B58\u5728: ${entryPath}`);
|
|
138
|
+
}
|
|
139
|
+
} else {
|
|
140
|
+
log(`\u9875\u9762 ${pageName} \u4E0D\u5728\u53EF\u7528\u5217\u8868\u4E2D`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
next();
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// src/build-config.ts
|
|
148
|
+
import * as path3 from "node:path";
|
|
149
|
+
import * as fs2 from "node:fs";
|
|
150
|
+
import { glob as glob2 } from "glob";
|
|
151
|
+
function simpleMatch(pattern, str) {
|
|
152
|
+
const regexPattern = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
153
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
154
|
+
return regex.test(str);
|
|
155
|
+
}
|
|
156
|
+
function createBuildConfig(config, options, log, tempFiles, pageMapping) {
|
|
157
|
+
var _a, _b, _c;
|
|
158
|
+
const allFiles = glob2.sync(options.entry, { cwd: process.cwd() });
|
|
159
|
+
const entryFiles = filterEntryFiles(allFiles, options.entry, options.exclude, log);
|
|
160
|
+
if (entryFiles.length === 0) {
|
|
161
|
+
console.warn("[vite-plugin-multi-page] No entry files found matching pattern:", options.entry);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
log("\u626B\u63CF\u5230\u7684\u6240\u6709\u6587\u4EF6:", allFiles);
|
|
165
|
+
log("\u8FC7\u6EE4\u540E\u7684\u5165\u53E3\u6587\u4EF6:", entryFiles);
|
|
166
|
+
const existingTempFiles = glob2.sync("temp-*.html", { cwd: process.cwd() });
|
|
167
|
+
existingTempFiles.forEach((file) => {
|
|
168
|
+
const fullPath = path3.resolve(process.cwd(), file);
|
|
169
|
+
if (fs2.existsSync(fullPath)) {
|
|
170
|
+
fs2.unlinkSync(fullPath);
|
|
171
|
+
log(`\u6E05\u7406\u65E7\u7684\u4E34\u65F6\u6587\u4EF6: ${file}`);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
const input = {};
|
|
175
|
+
tempFiles.length = 0;
|
|
176
|
+
pageMapping.clear();
|
|
177
|
+
const strategyGroups = {};
|
|
178
|
+
const defaultStrategy = "default";
|
|
179
|
+
entryFiles.forEach((entryFile) => {
|
|
180
|
+
const { name, file } = entryFile;
|
|
181
|
+
const pageConfig = getPageConfig(
|
|
182
|
+
options.pageConfigs,
|
|
183
|
+
{
|
|
184
|
+
pageName: name,
|
|
185
|
+
filePath: file,
|
|
186
|
+
relativePath: path3.relative(process.cwd(), file),
|
|
187
|
+
strategy: void 0,
|
|
188
|
+
isMatched: false
|
|
189
|
+
},
|
|
190
|
+
log
|
|
191
|
+
);
|
|
192
|
+
const strategy = (pageConfig == null ? void 0 : pageConfig.strategy) || defaultStrategy;
|
|
193
|
+
if (!strategyGroups[strategy]) {
|
|
194
|
+
strategyGroups[strategy] = [];
|
|
195
|
+
}
|
|
196
|
+
strategyGroups[strategy].push(entryFile);
|
|
197
|
+
const templatePath = (pageConfig == null ? void 0 : pageConfig.template) ? path3.resolve(process.cwd(), pageConfig.template) : path3.resolve(process.cwd(), options.template);
|
|
198
|
+
const tempHtmlPath = path3.resolve(process.cwd(), `temp-${name}.html`);
|
|
199
|
+
if (fs2.existsSync(templatePath)) {
|
|
200
|
+
let html = fs2.readFileSync(templatePath, "utf-8");
|
|
201
|
+
html = html.replace(new RegExp(escapeRegExp(options.placeholder), "g"), `/${file}`);
|
|
202
|
+
fs2.writeFileSync(tempHtmlPath, html);
|
|
203
|
+
tempFiles.push(tempHtmlPath);
|
|
204
|
+
input[name] = tempHtmlPath;
|
|
205
|
+
pageMapping.set(`temp-${name}.html`, `${name}.html`);
|
|
206
|
+
log(`\u521B\u5EFA\u4E34\u65F6\u6587\u4EF6: temp-${name}.html -> ${name}.html (\u7B56\u7565: ${strategy})`);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
log("Build input configuration:", input);
|
|
210
|
+
log("Strategy groups:", Object.keys(strategyGroups));
|
|
211
|
+
config.build = config.build || {};
|
|
212
|
+
config.build.rollupOptions = config.build.rollupOptions || {};
|
|
213
|
+
config.build.rollupOptions.input = input;
|
|
214
|
+
const defaultStrategyConfig = (_a = options.buildStrategies) == null ? void 0 : _a[defaultStrategy];
|
|
215
|
+
if (defaultStrategyConfig) {
|
|
216
|
+
applyBuildStrategy(config, defaultStrategyConfig, log);
|
|
217
|
+
}
|
|
218
|
+
const strategyKeys = Object.keys(strategyGroups);
|
|
219
|
+
if (strategyKeys.length === 1 && strategyKeys[0] !== defaultStrategy) {
|
|
220
|
+
const singleStrategy = (_b = options.buildStrategies) == null ? void 0 : _b[strategyKeys[0]];
|
|
221
|
+
if (singleStrategy) {
|
|
222
|
+
applyBuildStrategy(config, singleStrategy, log);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (strategyKeys.length > 1 || strategyKeys.length === 1 && strategyKeys[0] !== defaultStrategy && ((_c = options.buildStrategies) == null ? void 0 : _c[strategyKeys[0]])) {
|
|
226
|
+
log("\u68C0\u6D4B\u5230\u591A\u6784\u5EFA\u7B56\u7565\uFF0C\u5C06\u521B\u5EFA\u7B56\u7565\u6620\u5C04");
|
|
227
|
+
config.__multiPageStrategies = {
|
|
228
|
+
groups: strategyGroups,
|
|
229
|
+
strategies: options.buildStrategies,
|
|
230
|
+
pageConfigs: options.pageConfigs
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function getPageConfig(pageConfigs, context, log) {
|
|
235
|
+
if (!pageConfigs)
|
|
236
|
+
return null;
|
|
237
|
+
if (typeof pageConfigs === "function") {
|
|
238
|
+
const result = pageConfigs(context);
|
|
239
|
+
if (result) {
|
|
240
|
+
log(`\u51FD\u6570\u914D\u7F6E\u5339\u914D\u9875\u9762 ${context.pageName}:`, result);
|
|
241
|
+
}
|
|
242
|
+
return result;
|
|
243
|
+
}
|
|
244
|
+
for (const [key, config] of Object.entries(pageConfigs)) {
|
|
245
|
+
if (key === context.pageName) {
|
|
246
|
+
log(`\u7CBE\u786E\u5339\u914D\u9875\u9762 ${context.pageName}:`, config);
|
|
247
|
+
return config;
|
|
248
|
+
}
|
|
249
|
+
if (config.match) {
|
|
250
|
+
const patterns = Array.isArray(config.match) ? config.match : [config.match];
|
|
251
|
+
const isMatched = patterns.some(
|
|
252
|
+
(pattern) => simpleMatch(pattern, context.pageName) || simpleMatch(pattern, context.relativePath) || simpleMatch(pattern, context.filePath)
|
|
253
|
+
);
|
|
254
|
+
if (isMatched) {
|
|
255
|
+
log(`\u6A21\u5F0F\u5339\u914D\u9875\u9762 ${context.pageName} (\u6A21\u5F0F: ${config.match}):`, config);
|
|
256
|
+
return { ...config, match: void 0 };
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (simpleMatch(key, context.pageName)) {
|
|
260
|
+
log(`Glob\u5339\u914D\u9875\u9762 ${context.pageName} (\u6A21\u5F0F: ${key}):`, config);
|
|
261
|
+
return config;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
function applyBuildStrategy(config, strategy, log) {
|
|
267
|
+
log("\u5E94\u7528\u6784\u5EFA\u7B56\u7565:", strategy);
|
|
268
|
+
if (strategy.viteConfig) {
|
|
269
|
+
const { build: viteBuild, ...otherViteConfig } = strategy.viteConfig;
|
|
270
|
+
Object.keys(otherViteConfig).forEach((key) => {
|
|
271
|
+
if (key !== "plugins") {
|
|
272
|
+
const configKey = key;
|
|
273
|
+
const viteConfigValue = otherViteConfig[key];
|
|
274
|
+
if (viteConfigValue && typeof viteConfigValue === "object") {
|
|
275
|
+
config[configKey] = {
|
|
276
|
+
...config[configKey] || {},
|
|
277
|
+
...viteConfigValue
|
|
278
|
+
};
|
|
279
|
+
} else {
|
|
280
|
+
config[configKey] = viteConfigValue;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
if (viteBuild) {
|
|
285
|
+
config.build = {
|
|
286
|
+
...config.build,
|
|
287
|
+
...viteBuild
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (strategy.output) {
|
|
292
|
+
config.build.rollupOptions.output = {
|
|
293
|
+
...config.build.rollupOptions.output,
|
|
294
|
+
...strategy.output
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
if (strategy.build) {
|
|
298
|
+
config.build = {
|
|
299
|
+
...config.build,
|
|
300
|
+
...strategy.build
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
if (strategy.define) {
|
|
304
|
+
config.define = {
|
|
305
|
+
...config.define,
|
|
306
|
+
...strategy.define
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
if (strategy.alias) {
|
|
310
|
+
config.resolve = config.resolve || {};
|
|
311
|
+
config.resolve.alias = {
|
|
312
|
+
...config.resolve.alias,
|
|
313
|
+
...strategy.alias
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
if (strategy.server) {
|
|
317
|
+
config.server = {
|
|
318
|
+
...config.server,
|
|
319
|
+
...strategy.server
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
if (strategy.css) {
|
|
323
|
+
config.css = {
|
|
324
|
+
...config.css,
|
|
325
|
+
...strategy.css
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
if (strategy.optimizeDeps) {
|
|
329
|
+
config.optimizeDeps = {
|
|
330
|
+
...config.optimizeDeps,
|
|
331
|
+
...strategy.optimizeDeps
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
function createDevConfig(options, log) {
|
|
336
|
+
const allFiles = glob2.sync(options.entry, { cwd: process.cwd() });
|
|
337
|
+
const entryFiles = filterEntryFiles(allFiles, options.entry, options.exclude, log);
|
|
338
|
+
const input = {};
|
|
339
|
+
entryFiles.forEach(({ name, file }) => {
|
|
340
|
+
input[name] = path3.resolve(process.cwd(), file);
|
|
341
|
+
});
|
|
342
|
+
log("Dev input configuration:", input);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// src/index.ts
|
|
346
|
+
function viteMultiPage(options = {}) {
|
|
347
|
+
const {
|
|
348
|
+
entry = "src/**/*.{ts,js}",
|
|
349
|
+
template = "index.html",
|
|
350
|
+
exclude = ["src/main.ts", "src/vite-env.d.ts"],
|
|
351
|
+
placeholder = "{{ENTRY_FILE}}",
|
|
352
|
+
debug = false,
|
|
353
|
+
buildStrategies,
|
|
354
|
+
pageConfigs
|
|
355
|
+
} = options;
|
|
356
|
+
const log = createLogger(debug);
|
|
357
|
+
let tempFiles = [];
|
|
358
|
+
const pageMapping = /* @__PURE__ */ new Map();
|
|
359
|
+
return {
|
|
360
|
+
name: "vite-plugin-multi-page",
|
|
361
|
+
config(config, { command }) {
|
|
362
|
+
if (command === "build") {
|
|
363
|
+
createBuildConfig(
|
|
364
|
+
config,
|
|
365
|
+
{ entry, exclude, template, placeholder, buildStrategies, pageConfigs },
|
|
366
|
+
log,
|
|
367
|
+
tempFiles,
|
|
368
|
+
pageMapping
|
|
369
|
+
);
|
|
370
|
+
} else {
|
|
371
|
+
createDevConfig({ entry, exclude }, log);
|
|
372
|
+
}
|
|
373
|
+
},
|
|
374
|
+
configureServer(server) {
|
|
375
|
+
configureDevServer(server, { entry, exclude, template, placeholder }, log);
|
|
376
|
+
},
|
|
377
|
+
generateBundle() {
|
|
378
|
+
},
|
|
379
|
+
writeBundle(options2) {
|
|
380
|
+
Array.from(pageMapping.entries()).forEach(([tempName, targetName]) => {
|
|
381
|
+
const tempPath = path4.resolve(options2.dir || "dist", tempName);
|
|
382
|
+
const targetPath = path4.resolve(options2.dir || "dist", targetName);
|
|
383
|
+
if (fs3.existsSync(tempPath)) {
|
|
384
|
+
fs3.renameSync(tempPath, targetPath);
|
|
385
|
+
log(`\u91CD\u547D\u540DHTML\u6587\u4EF6: ${tempName} -> ${targetName}`);
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
},
|
|
389
|
+
closeBundle() {
|
|
390
|
+
tempFiles.forEach((filePath) => {
|
|
391
|
+
if (fs3.existsSync(filePath)) {
|
|
392
|
+
fs3.unlinkSync(filePath);
|
|
393
|
+
const fileName = path4.basename(filePath);
|
|
394
|
+
log(`\u6E05\u7406\u4E34\u65F6\u6587\u4EF6: ${fileName}`);
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
tempFiles = [];
|
|
398
|
+
pageMapping.clear();
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
export {
|
|
403
|
+
viteMultiPage as default,
|
|
404
|
+
viteMultiPage
|
|
405
|
+
};
|
|
406
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/dev-server.ts","../src/file-filter.ts","../src/build-config.ts"],"sourcesContent":["import type { Plugin } from 'vite';\nimport * as path from 'node:path';\nimport * as fs from 'node:fs';\nimport type { MultiPageOptions } from './types';\nimport { createLogger } from './utils';\nimport { configureDevServer } from './dev-server';\nimport { createBuildConfig, createDevConfig } from './build-config';\n\nexport type { MultiPageOptions };\n\nexport default function viteMultiPage(options: MultiPageOptions = {}): Plugin {\n const {\n entry = 'src/**/*.{ts,js}',\n template = 'index.html',\n exclude = ['src/main.ts', 'src/vite-env.d.ts'],\n placeholder = '{{ENTRY_FILE}}',\n debug = false,\n buildStrategies,\n pageConfigs,\n } = options;\n\n const log = createLogger(debug);\n let tempFiles: string[] = [];\n const pageMapping: Map<string, string> = new Map();\n\n return {\n name: 'vite-plugin-multi-page',\n\n config(config: any, { command }: { command: string }) {\n if (command === 'build') {\n createBuildConfig(\n config,\n { entry, exclude, template, placeholder, buildStrategies, pageConfigs },\n log,\n tempFiles,\n pageMapping\n );\n } else {\n createDevConfig({ entry, exclude }, log);\n }\n },\n\n configureServer(server) {\n configureDevServer(server, { entry, exclude, template, placeholder }, log);\n },\n\n generateBundle() {\n // 用于处理JS/CSS资源,HTML在writeBundle中处理\n },\n\n writeBundle(options: any) {\n Array.from(pageMapping.entries()).forEach(([tempName, targetName]) => {\n const tempPath = path.resolve(options.dir || 'dist', tempName);\n const targetPath = path.resolve(options.dir || 'dist', targetName);\n\n if (fs.existsSync(tempPath)) {\n fs.renameSync(tempPath, targetPath);\n log(`重命名HTML文件: ${tempName} -> ${targetName}`);\n }\n });\n },\n\n closeBundle() {\n tempFiles.forEach(filePath => {\n if (fs.existsSync(filePath)) {\n fs.unlinkSync(filePath);\n const fileName = path.basename(filePath);\n log(`清理临时文件: ${fileName}`);\n }\n });\n tempFiles = [];\n pageMapping.clear();\n },\n };\n}\n\nexport { viteMultiPage };\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 { 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';\n\nexport function configureDevServer(\n server: ViteDevServer,\n options: {\n entry: string;\n exclude: string[];\n template: string;\n placeholder: string;\n },\n log: (...args: any[]) => void\n) {\n const allFiles = glob.sync(options.entry, { cwd: process.cwd() });\n const entryFiles = filterEntryFiles(allFiles, options.entry, options.exclude, log);\n\n const pageMap = new Map<string, string>();\n entryFiles.forEach(({ name, file }) => {\n pageMap.set(name, file);\n });\n\n const pageNames = Array.from(pageMap.keys());\n log('Available pages:', pageNames);\n log('Page mapping:', Object.fromEntries(pageMap));\n\n server.middlewares.use((req: any, res: any, next: any) => {\n const originalUrl = req.url;\n const url = originalUrl?.split('?')[0];\n\n if (!url) {\n return next();\n }\n\n log(`处理请求: ${url}`);\n\n if (url === '/' && pageNames.length > 0) {\n const defaultPage = pageNames.includes('index') ? 'index' : pageNames[0];\n log(`根路径重定向到: ${defaultPage}`);\n req.url = `/${defaultPage}.html`;\n }\n\n const finalUrl = req.url?.split('?')[0];\n // eslint-disable-next-line no-useless-escape\n const pageMatch = finalUrl?.match(/^\\/([^\\/\\.]+)(\\.html)?$/);\n\n if (pageMatch) {\n const pageName = pageMatch[1];\n\n log(`匹配到页面: ${pageName}`);\n log(`可用页面列表: ${pageNames.join(', ')}`);\n\n if (pageMap.has(pageName)) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const relativeEntryPath = pageMap.get(pageName)!;\n const entryPath = path.resolve(process.cwd(), relativeEntryPath);\n\n log(`页面 ${pageName} 对应文件: ${relativeEntryPath}`);\n\n if (fs.existsSync(entryPath)) {\n log(`找到入口文件: ${entryPath}`);\n\n const templatePath = path.resolve(process.cwd(), options.template);\n\n if (fs.existsSync(templatePath)) {\n let html = fs.readFileSync(templatePath, 'utf-8');\n\n log(`读取模板文件: ${templatePath}`);\n log(`模板内容包含占位符: ${html.includes(options.placeholder)}`);\n\n if (!html.includes(options.placeholder)) {\n console.warn(\n `[vite-plugin-multi-page] 模板文件中没有找到占位符: ${options.placeholder}`\n );\n return next();\n }\n\n const entryFile = `/${relativeEntryPath}`;\n html = html.replace(new RegExp(escapeRegExp(options.placeholder), 'g'), entryFile);\n\n log(`占位符 ${options.placeholder} 替换为: ${entryFile}`);\n log(`替换后包含占位符: ${html.includes(options.placeholder)}`);\n\n res.setHeader('Content-Type', 'text/html');\n res.end(html);\n return;\n } else {\n log(`模板文件不存在: ${templatePath}`);\n }\n } else {\n log(`入口文件不存在: ${entryPath}`);\n }\n } else {\n log(`页面 ${pageName} 不在可用列表中`);\n }\n }\n\n next();\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, string>();\n\n const basePattern = entry.replace(/\\/\\*\\*.*$/, '');\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 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 const fileName = path.basename(file, path.extname(file));\n const dirName = pathParts[0];\n\n if (fileName === 'main') {\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 for (const candidate of candidateFiles) {\n const existing = nameToFile.get(candidate.name);\n\n if (!existing) {\n nameToFile.set(candidate.name, candidate.file);\n log(`✅ 添加页面: ${candidate.name} -> ${candidate.file}`);\n } else {\n const existingCandidate = candidateFiles.find(c => c.file === existing);\n if (existingCandidate && candidate.priority > existingCandidate.priority) {\n nameToFile.set(candidate.name, candidate.file);\n log(`🔄 替换页面: ${candidate.name} -> ${candidate.file} (替换 ${existing})`);\n } else {\n log(`⚠️ 冲突跳过: ${candidate.name} -> ${candidate.file} (保留 ${existing})`);\n }\n }\n }\n\n for (const [name, file] of nameToFile.entries()) {\n result.push({ name, file });\n }\n\n return result;\n}\n","import * 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 type { BuildStrategy, PageConfig, PageConfigFunction, PageConfigContext } from './types';\n\n// 简单的 glob 模式匹配函数\nfunction simpleMatch(pattern: string, str: string): boolean {\n const regexPattern = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&') // 转义特殊字符\n .replace(/\\*/g, '.*') // * 匹配任意字符\n .replace(/\\?/g, '.'); // ? 匹配单个字符\n\n const regex = new RegExp(`^${regexPattern}$`);\n return regex.test(str);\n}\n\nexport function createBuildConfig(\n config: any,\n options: {\n entry: string;\n exclude: string[];\n template: string;\n placeholder: string;\n buildStrategies?: Record<string, BuildStrategy>;\n pageConfigs?: Record<string, PageConfig> | PageConfigFunction;\n },\n log: (...args: any[]) => void,\n tempFiles: string[],\n pageMapping: Map<string, string>\n) {\n const allFiles = glob.sync(options.entry, { cwd: process.cwd() });\n const entryFiles = filterEntryFiles(allFiles, options.entry, options.exclude, log);\n\n if (entryFiles.length === 0) {\n console.warn('[vite-plugin-multi-page] No entry files found matching pattern:', options.entry);\n return;\n }\n\n log('扫描到的所有文件:', allFiles);\n log('过滤后的入口文件:', entryFiles);\n\n // 清理旧的临时文件\n const existingTempFiles = glob.sync('temp-*.html', { cwd: process.cwd() });\n existingTempFiles.forEach(file => {\n const fullPath = path.resolve(process.cwd(), file);\n if (fs.existsSync(fullPath)) {\n fs.unlinkSync(fullPath);\n log(`清理旧的临时文件: ${file}`);\n }\n });\n\n const input: Record<string, string> = {};\n tempFiles.length = 0; // 清空数组\n pageMapping.clear();\n\n // 分组页面按构建策略\n const strategyGroups: Record<string, typeof entryFiles> = {};\n const defaultStrategy = 'default';\n\n entryFiles.forEach(entryFile => {\n const { name, file } = entryFile;\n\n // 获取页面配置\n const pageConfig = getPageConfig(\n options.pageConfigs,\n {\n pageName: name,\n filePath: file,\n relativePath: path.relative(process.cwd(), file),\n strategy: undefined,\n isMatched: false,\n },\n log\n );\n\n const strategy = pageConfig?.strategy || defaultStrategy;\n\n if (!strategyGroups[strategy]) {\n strategyGroups[strategy] = [];\n }\n strategyGroups[strategy].push(entryFile);\n\n // 创建HTML文件\n const templatePath = pageConfig?.template\n ? path.resolve(process.cwd(), pageConfig.template)\n : path.resolve(process.cwd(), options.template);\n\n const tempHtmlPath = path.resolve(process.cwd(), `temp-${name}.html`);\n\n if (fs.existsSync(templatePath)) {\n let html = fs.readFileSync(templatePath, 'utf-8');\n html = html.replace(new RegExp(escapeRegExp(options.placeholder), 'g'), `/${file}`);\n\n fs.writeFileSync(tempHtmlPath, html);\n tempFiles.push(tempHtmlPath);\n\n input[name] = tempHtmlPath;\n pageMapping.set(`temp-${name}.html`, `${name}.html`);\n\n log(`创建临时文件: temp-${name}.html -> ${name}.html (策略: ${strategy})`);\n }\n });\n\n log('Build input configuration:', input);\n log('Strategy groups:', Object.keys(strategyGroups));\n\n // 应用构建策略\n config.build = config.build || {};\n config.build.rollupOptions = config.build.rollupOptions || {};\n config.build.rollupOptions.input = input;\n\n // 应用默认或指定的构建策略\n const defaultStrategyConfig = options.buildStrategies?.[defaultStrategy];\n if (defaultStrategyConfig) {\n applyBuildStrategy(config, defaultStrategyConfig, log);\n }\n\n // 如果只有一个策略组且不是默认策略,应用该策略\n const strategyKeys = Object.keys(strategyGroups);\n if (strategyKeys.length === 1 && strategyKeys[0] !== defaultStrategy) {\n const singleStrategy = options.buildStrategies?.[strategyKeys[0]];\n if (singleStrategy) {\n applyBuildStrategy(config, singleStrategy, log);\n }\n }\n\n // 处理多策略情况(需要多次构建)\n if (\n strategyKeys.length > 1 ||\n (strategyKeys.length === 1 &&\n strategyKeys[0] !== defaultStrategy &&\n options.buildStrategies?.[strategyKeys[0]])\n ) {\n log('检测到多构建策略,将创建策略映射');\n // 在插件实例上存储策略信息,供后续处理\n (config as any).__multiPageStrategies = {\n groups: strategyGroups,\n strategies: options.buildStrategies,\n pageConfigs: options.pageConfigs,\n };\n }\n}\n\nfunction 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 }; // 移除 match 属性避免传递给构建配置\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\nfunction applyBuildStrategy(config: any, strategy: BuildStrategy, log: (...args: any[]) => void) {\n log('应用构建策略:', strategy);\n\n // 应用完整的 Vite 配置\n if (strategy.viteConfig) {\n const { build: viteBuild, ...otherViteConfig } = strategy.viteConfig;\n\n // 合并非构建配置\n Object.keys(otherViteConfig).forEach(key => {\n if (key !== 'plugins') {\n // 跳过 plugins,避免冲突\n const configKey = key as keyof typeof config;\n const viteConfigValue = otherViteConfig[key as keyof typeof otherViteConfig];\n if (viteConfigValue && typeof viteConfigValue === 'object') {\n config[configKey] = {\n ...(config[configKey] || {}),\n ...viteConfigValue,\n };\n } else {\n config[configKey] = viteConfigValue;\n }\n }\n });\n\n // 合并构建配置\n if (viteBuild) {\n config.build = {\n ...config.build,\n ...viteBuild,\n };\n }\n }\n\n // 应用输出配置\n if (strategy.output) {\n config.build.rollupOptions.output = {\n ...config.build.rollupOptions.output,\n ...strategy.output,\n };\n }\n\n // 应用构建配置\n if (strategy.build) {\n config.build = {\n ...config.build,\n ...strategy.build,\n };\n }\n\n // 应用环境变量\n if (strategy.define) {\n config.define = {\n ...config.define,\n ...strategy.define,\n };\n }\n\n // 应用别名配置\n if (strategy.alias) {\n config.resolve = config.resolve || {};\n config.resolve.alias = {\n ...config.resolve.alias,\n ...strategy.alias,\n };\n }\n\n // 应用服务器配置\n if (strategy.server) {\n config.server = {\n ...config.server,\n ...strategy.server,\n };\n }\n\n // 应用 CSS 配置\n if (strategy.css) {\n config.css = {\n ...config.css,\n ...strategy.css,\n };\n }\n\n // 应用优化依赖配置\n if (strategy.optimizeDeps) {\n config.optimizeDeps = {\n ...config.optimizeDeps,\n ...strategy.optimizeDeps,\n };\n }\n}\n\nexport function createDevConfig(\n options: {\n entry: string;\n exclude: string[];\n },\n log: (...args: any[]) => void\n) {\n const allFiles = glob.sync(options.entry, { cwd: process.cwd() });\n const entryFiles = filterEntryFiles(allFiles, options.entry, options.exclude, log);\n\n const input: Record<string, string> = {};\n entryFiles.forEach(({ name, file }) => {\n input[name] = path.resolve(process.cwd(), file);\n });\n log('Dev input configuration:', input);\n}\n"],"mappings":"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","names":["path","fs","path","path","fs","glob","glob","options"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fchc8/vite-plugin-multi-page",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A Vite plugin for building multi-page applications with smart file routing",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md",
|
|
11
|
+
"README-EN.md",
|
|
12
|
+
"LICENSE"
|
|
13
|
+
],
|
|
14
|
+
"keywords": [
|
|
15
|
+
"vite",
|
|
16
|
+
"plugin",
|
|
17
|
+
"multi-page",
|
|
18
|
+
"mpa",
|
|
19
|
+
"vite-plugin",
|
|
20
|
+
"routing",
|
|
21
|
+
"file-based",
|
|
22
|
+
"typescript"
|
|
23
|
+
],
|
|
24
|
+
"author": "Your Name <your.email@example.com>",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"homepage": "https://github.com/your-username/vite-plugin-multi-page#readme",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/your-username/vite-plugin-multi-page.git"
|
|
30
|
+
},
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/your-username/vite-plugin-multi-page/issues"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsup",
|
|
36
|
+
"dev": "tsup --watch",
|
|
37
|
+
"type-check": "tsc --noEmit",
|
|
38
|
+
"lint": "eslint src --ext .ts --fix",
|
|
39
|
+
"format": "prettier --write \"src/**/*.{ts,js,json}\"",
|
|
40
|
+
"format:check": "prettier --check \"src/**/*.{ts,js,json}\"",
|
|
41
|
+
"test": "echo 'No tests yet'",
|
|
42
|
+
"clean": "rm -rf dist",
|
|
43
|
+
"example:dev": "cd example && pnpm run dev",
|
|
44
|
+
"example:build": "cd example && pnpm run build",
|
|
45
|
+
"example:preview": "cd example && pnpm run preview",
|
|
46
|
+
"pre-release": "bash scripts/pre-release-check.sh",
|
|
47
|
+
"prepack": "pnpm run clean && pnpm run type-check && pnpm run lint && pnpm run format:check && pnpm run build",
|
|
48
|
+
"prepublishOnly": "pnpm run prepack",
|
|
49
|
+
"postpublish": "git push && git push --tags",
|
|
50
|
+
"version:patch": "npm version patch",
|
|
51
|
+
"version:minor": "npm version minor",
|
|
52
|
+
"version:major": "npm version major",
|
|
53
|
+
"release:patch": "npm run version:patch && npm publish",
|
|
54
|
+
"release:minor": "npm run version:minor && npm publish",
|
|
55
|
+
"release:major": "npm run version:major && npm publish",
|
|
56
|
+
"release:beta": "npm version prerelease --preid=beta && npm publish --tag beta",
|
|
57
|
+
"release:alpha": "npm version prerelease --preid=alpha && npm publish --tag alpha",
|
|
58
|
+
"git:init-flow": "git flow init -d",
|
|
59
|
+
"git:feature": "bash scripts/git-feature.sh",
|
|
60
|
+
"git:hotfix": "bash scripts/git-hotfix.sh",
|
|
61
|
+
"git:release": "bash scripts/git-release.sh"
|
|
62
|
+
},
|
|
63
|
+
"peerDependencies": {
|
|
64
|
+
"vite": "^4.0.0 || ^5.0.0"
|
|
65
|
+
},
|
|
66
|
+
"dependencies": {
|
|
67
|
+
"glob": "^10.0.0"
|
|
68
|
+
},
|
|
69
|
+
"devDependencies": {
|
|
70
|
+
"@types/node": "^20.0.0",
|
|
71
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
72
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
73
|
+
"eslint": "^8.0.0",
|
|
74
|
+
"eslint-config-prettier": "^9.0.0",
|
|
75
|
+
"eslint-plugin-prettier": "^5.0.0",
|
|
76
|
+
"prettier": "^3.0.0",
|
|
77
|
+
"tsup": "^8.0.0",
|
|
78
|
+
"typescript": "^5.0.2",
|
|
79
|
+
"vite": "^5.4.0"
|
|
80
|
+
},
|
|
81
|
+
"engines": {
|
|
82
|
+
"node": ">=16"
|
|
83
|
+
},
|
|
84
|
+
"publishConfig": {
|
|
85
|
+
"access": "public",
|
|
86
|
+
"registry": "https://registry.npmjs.org/"
|
|
87
|
+
}
|
|
88
|
+
}
|