@fchc8/vite-plugin-multi-page 1.6.0 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README-EN.md +95 -60
- package/README.md +1 -1
- package/dist/cli.js +186 -185
- package/package.json +1 -1
package/README-EN.md
CHANGED
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
> 中文文档 | [中文文档](./README.md)
|
|
4
4
|
|
|
5
|
-
A powerful Vite plugin for
|
|
5
|
+
A powerful Vite plugin for multi-page application development, providing multi-strategy builds, TypeScript configuration support, and command-line tools.
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
- 🎯 **Multi-page support**: Automatically discover page entry files
|
|
10
|
-
- 🔧 **Multi-strategy builds**: Support configuring different
|
|
10
|
+
- 🔧 **Multi-strategy builds**: Support configuring different builds for different pages
|
|
11
11
|
- 📝 **TypeScript configuration**: Support TypeScript configuration files
|
|
12
|
-
- 🚀 **CLI tool**: Provide
|
|
12
|
+
- 🚀 **CLI tool**: Provide command-line batch build tools
|
|
13
13
|
- 🔄 **Hot reload**: Development server supports page hot reload
|
|
14
14
|
- 📦 **Smart merge**: Automatically merge multi-strategy build results
|
|
15
15
|
|
|
16
|
-
##
|
|
16
|
+
## Install
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
19
|
npm install @fchc8/vite-plugin-multi-page --save-dev
|
|
@@ -21,32 +21,78 @@ npm install @fchc8/vite-plugin-multi-page --save-dev
|
|
|
21
21
|
|
|
22
22
|
## Quick Start
|
|
23
23
|
|
|
24
|
-
### 1.
|
|
24
|
+
### 1. Configure Vite
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
Add the plugin in `vite.config.ts`:
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { defineConfig } from 'vite';
|
|
30
|
+
import { viteMultiPage } from '@fchc8/vite-plugin-multi-page';
|
|
31
|
+
|
|
32
|
+
export default defineConfig({
|
|
33
|
+
plugins: [viteMultiPage()],
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2. Create Configuration File (Optional)
|
|
38
|
+
|
|
39
|
+
The plugin provides reasonable default configurations, you can choose:
|
|
40
|
+
|
|
41
|
+
**Option A: No Configuration File (Use Default Configuration)**
|
|
42
|
+
|
|
43
|
+
- Automatically scan for page files under `src/pages/**/*.{ts,js}`, and the file with the name main as the page entry
|
|
44
|
+
- Use `index.html` as the template
|
|
45
|
+
- Create default build strategy
|
|
46
|
+
|
|
47
|
+
**Option B: Simplest Configuration**
|
|
48
|
+
|
|
49
|
+
Create `multipage.config.ts`:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { defineConfig } from '@fchc8/vite-plugin-multi-page';
|
|
53
|
+
|
|
54
|
+
// Use all default values
|
|
55
|
+
export default defineConfig(() => ({}));
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Option C: Complete Configuration**
|
|
59
|
+
|
|
60
|
+
Create `multipage.config.ts` or `multipage.config.js`:
|
|
27
61
|
|
|
28
62
|
```typescript
|
|
29
|
-
|
|
63
|
+
import { defineConfig } from 'vite-plugin-multi-page';
|
|
64
|
+
|
|
65
|
+
// Method 1: Object Configuration (Recommended)
|
|
66
|
+
export default defineConfig({
|
|
67
|
+
entry: 'src/pages/**/*.{ts,js}',
|
|
68
|
+
template: 'index.html',
|
|
69
|
+
strategies: {
|
|
70
|
+
// Strategy Configuration...
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Method 2: Function Configuration (Dynamic Configuration)
|
|
75
|
+
export default defineConfig(context => {
|
|
30
76
|
const { mode, command, isCLI } = context;
|
|
31
77
|
const isProduction = mode === 'production';
|
|
32
78
|
|
|
33
79
|
return {
|
|
34
|
-
// Page entry matching
|
|
80
|
+
// Page entry matching rules
|
|
35
81
|
entry: 'src/pages/**/*.{ts,js}',
|
|
36
82
|
|
|
37
|
-
// HTML
|
|
83
|
+
// HTML Template
|
|
38
84
|
template: 'index.html',
|
|
39
85
|
|
|
40
|
-
// Template
|
|
86
|
+
// Template Placeholder
|
|
41
87
|
placeholder: '{{ENTRY_FILE}}',
|
|
42
88
|
|
|
43
|
-
// Excluded
|
|
89
|
+
// Excluded Files
|
|
44
90
|
exclude: ['src/shared/**/*.ts'],
|
|
45
91
|
|
|
46
|
-
// Debug
|
|
92
|
+
// Debug Mode
|
|
47
93
|
debug: !isProduction || isCLI,
|
|
48
94
|
|
|
49
|
-
// Build
|
|
95
|
+
// Build Strategy
|
|
50
96
|
strategies: {
|
|
51
97
|
default: {
|
|
52
98
|
define: {
|
|
@@ -73,9 +119,9 @@ export default context => {
|
|
|
73
119
|
},
|
|
74
120
|
},
|
|
75
121
|
|
|
76
|
-
// Page
|
|
122
|
+
// Page Configuration Function
|
|
77
123
|
pageConfigs: context => {
|
|
78
|
-
// Determine the
|
|
124
|
+
// Determine the strategy based on the file path
|
|
79
125
|
if (context.relativePath.includes('/mobile/')) {
|
|
80
126
|
return {
|
|
81
127
|
strategy: 'mobile',
|
|
@@ -86,7 +132,7 @@ export default context => {
|
|
|
86
132
|
};
|
|
87
133
|
}
|
|
88
134
|
|
|
89
|
-
// Default
|
|
135
|
+
// Default Strategy
|
|
90
136
|
return {
|
|
91
137
|
strategy: 'default',
|
|
92
138
|
define: {
|
|
@@ -96,50 +142,39 @@ export default context => {
|
|
|
96
142
|
};
|
|
97
143
|
},
|
|
98
144
|
};
|
|
99
|
-
};
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### 2. Configure Vite
|
|
103
|
-
|
|
104
|
-
Add the plugin in `vite.config.ts`:
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
import { defineConfig } from 'vite';
|
|
108
|
-
import { viteMultiPage } from '@fchc8/vite-plugin-multi-page';
|
|
109
|
-
|
|
110
|
-
export default defineConfig({
|
|
111
|
-
plugins: [viteMultiPage()],
|
|
112
145
|
});
|
|
113
146
|
```
|
|
114
147
|
|
|
115
|
-
### 3. Create
|
|
148
|
+
### 3. Create Page Files
|
|
116
149
|
|
|
117
150
|
Create page files according to the convention:
|
|
118
151
|
|
|
152
|
+
**Note**: Even if you use the empty configuration `defineConfig({})`, the plugin will automatically use the default strategy to process all pages, ensuring maximum compatibility.
|
|
153
|
+
|
|
119
154
|
```
|
|
120
155
|
src/pages/
|
|
121
156
|
├── home.js # → /home.html
|
|
122
|
-
├── about.js # → /about.html
|
|
157
|
+
├── about.js # → /about.html (Default Strategy)
|
|
123
158
|
├── mobile/
|
|
124
|
-
│ └── main.ts # → /mobile.html (
|
|
159
|
+
│ └── main.ts # → /mobile.html (Mobile Strategy)
|
|
125
160
|
└── admin/
|
|
126
|
-
└── main.ts # → /admin.html
|
|
161
|
+
└── main.ts # → /admin.html (Admin Strategy)
|
|
127
162
|
```
|
|
128
163
|
|
|
129
|
-
## Page
|
|
164
|
+
## Page Discovery Rules
|
|
130
165
|
|
|
131
166
|
The plugin discovers page entries according to the following rules:
|
|
132
167
|
|
|
133
|
-
1. **First-level
|
|
134
|
-
2. **Directory main files** (
|
|
168
|
+
1. **First-level Files** (Priority 1): `src/pages/home.js` → `/home.html`
|
|
169
|
+
2. **Directory main files** (Priority 2): `src/pages/mobile/main.ts` → `/mobile.html`
|
|
135
170
|
|
|
136
|
-
**Directory
|
|
171
|
+
**Directory Priority Principle**: If both `src/pages/about.js` and `src/pages/about/main.ts` exist, `src/pages/about/main.ts` will be used.
|
|
137
172
|
|
|
138
|
-
## Build
|
|
173
|
+
## Build Strategy
|
|
139
174
|
|
|
140
|
-
### Strategy
|
|
175
|
+
### Strategy Configuration
|
|
141
176
|
|
|
142
|
-
|
|
177
|
+
Strategy configuration supports all Vite configuration options:
|
|
143
178
|
|
|
144
179
|
```typescript
|
|
145
180
|
strategies: {
|
|
@@ -161,7 +196,7 @@ strategies: {
|
|
|
161
196
|
}
|
|
162
197
|
```
|
|
163
198
|
|
|
164
|
-
### Page
|
|
199
|
+
### Page Strategy Assignment
|
|
165
200
|
|
|
166
201
|
Assign strategies to pages through the `pageConfigs` function:
|
|
167
202
|
|
|
@@ -181,9 +216,9 @@ pageConfigs: context => {
|
|
|
181
216
|
};
|
|
182
217
|
```
|
|
183
218
|
|
|
184
|
-
##
|
|
219
|
+
## Command Line Tool
|
|
185
220
|
|
|
186
|
-
###
|
|
221
|
+
### Batch Build
|
|
187
222
|
|
|
188
223
|
```bash
|
|
189
224
|
# Build all strategies
|
|
@@ -196,7 +231,7 @@ npx vite-mp --host --port 3000
|
|
|
196
231
|
npx vite-mp --debug
|
|
197
232
|
```
|
|
198
233
|
|
|
199
|
-
###
|
|
234
|
+
### Development Server
|
|
200
235
|
|
|
201
236
|
```bash
|
|
202
237
|
# Start development server (all pages)
|
|
@@ -206,13 +241,13 @@ npm run dev
|
|
|
206
241
|
npm run dev -- --strategy mobile
|
|
207
242
|
```
|
|
208
243
|
|
|
209
|
-
## Environment
|
|
244
|
+
## Environment Variables
|
|
210
245
|
|
|
211
246
|
- `VITE_BUILD_STRATEGY`: Specify a single strategy build
|
|
212
247
|
- `IS_MOBILE`: Mobile identifier (configured in define)
|
|
213
248
|
- `API_BASE`: API base address (configured in define)
|
|
214
249
|
|
|
215
|
-
## TypeScript
|
|
250
|
+
## TypeScript Support
|
|
216
251
|
|
|
217
252
|
The plugin fully supports TypeScript configuration files:
|
|
218
253
|
|
|
@@ -230,21 +265,21 @@ const config: ConfigFunction = context => {
|
|
|
230
265
|
export default config;
|
|
231
266
|
```
|
|
232
267
|
|
|
233
|
-
## API
|
|
268
|
+
## API Reference
|
|
234
269
|
|
|
235
|
-
### Configuration
|
|
270
|
+
### Configuration Options
|
|
236
271
|
|
|
237
|
-
| Option | Type | Default
|
|
238
|
-
| ------------- | -------------------------- | -------------------------- |
|
|
239
|
-
| `entry` | `string` | `'src/pages/**/*.{ts,js}'` | Page entry matching
|
|
240
|
-
| `template` | `string` | `'index.html'` | HTML
|
|
241
|
-
| `placeholder` | `string` | `'{{ENTRY_FILE}}'` |
|
|
242
|
-
| `exclude` | `string[]` | `[]` |
|
|
243
|
-
| `debug` | `boolean` | `false` |
|
|
244
|
-
| `strategies` | `Record<string, Strategy>` | `{}` |
|
|
245
|
-
| `pageConfigs` | `Function \| Object` | `{}` |
|
|
272
|
+
| Option | Type | Default Value | Description |
|
|
273
|
+
| ------------- | -------------------------- | -------------------------- | ------------------------- |
|
|
274
|
+
| `entry` | `string` | `'src/pages/**/*.{ts,js}'` | Page entry matching rules |
|
|
275
|
+
| `template` | `string` | `'index.html'` | HTML Template File |
|
|
276
|
+
| `placeholder` | `string` | `'{{ENTRY_FILE}}'` | 模板占位符 |
|
|
277
|
+
| `exclude` | `string[]` | `[]` | 排除的文件模式 |
|
|
278
|
+
| `debug` | `boolean` | `false` | 启用调试日志 |
|
|
279
|
+
| `strategies` | `Record<string, Strategy>` | `{}` | 构建策略配置 |
|
|
280
|
+
| `pageConfigs` | `Function \| Object` | `{}` | 页面配置 |
|
|
246
281
|
|
|
247
|
-
### Utility
|
|
282
|
+
### Utility Functions
|
|
248
283
|
|
|
249
284
|
```typescript
|
|
250
285
|
import { defineConfig, defineConfigTransform } from '@fchc8/vite-plugin-multi-page';
|
|
@@ -261,9 +296,9 @@ const transform = defineConfigTransform((config, context) => {
|
|
|
261
296
|
});
|
|
262
297
|
```
|
|
263
298
|
|
|
264
|
-
## Example
|
|
299
|
+
## Example Project
|
|
265
300
|
|
|
266
|
-
See [example](./example) directory for
|
|
301
|
+
See [example](./example) directory for the complete example project.
|
|
267
302
|
|
|
268
303
|
## License
|
|
269
304
|
|
package/README.md
CHANGED
package/dist/cli.js
CHANGED
|
@@ -38,179 +38,27 @@ var init_cjs_shims = __esm({
|
|
|
38
38
|
}
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
// src/config-loader.ts
|
|
42
|
-
var config_loader_exports = {};
|
|
43
|
-
__export(config_loader_exports, {
|
|
44
|
-
hasCustomConfig: () => hasCustomConfig,
|
|
45
|
-
loadUserConfig: () => loadUserConfig
|
|
46
|
-
});
|
|
47
|
-
function hasCustomConfig() {
|
|
48
|
-
for (const filename of CONFIG_FILES) {
|
|
49
|
-
const configPath = path.resolve(process.cwd(), filename);
|
|
50
|
-
if (fs.existsSync(configPath)) {
|
|
51
|
-
return true;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
async function loadUserConfig(context) {
|
|
57
|
-
const customConfig = await loadCustomConfig();
|
|
58
|
-
if (customConfig) {
|
|
59
|
-
const result = customConfig(context);
|
|
60
|
-
if (!result) {
|
|
61
|
-
return {};
|
|
62
|
-
}
|
|
63
|
-
return result;
|
|
64
|
-
}
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
async function loadConfigFile(filePath) {
|
|
68
|
-
if (filePath.endsWith(".ts")) {
|
|
69
|
-
try {
|
|
70
|
-
const code = await fs.promises.readFile(filePath, "utf-8");
|
|
71
|
-
const esbuild = await import("esbuild");
|
|
72
|
-
const result = await esbuild.transform(code, {
|
|
73
|
-
loader: "ts",
|
|
74
|
-
format: "cjs",
|
|
75
|
-
// 使用 CommonJS 格式便于使用 Module._compile
|
|
76
|
-
target: "node16",
|
|
77
|
-
sourcemap: false
|
|
78
|
-
});
|
|
79
|
-
const tempModule = new import_node_module.Module(filePath);
|
|
80
|
-
tempModule.filename = filePath;
|
|
81
|
-
tempModule.paths = import_node_module.Module._nodeModulePaths(path.dirname(filePath));
|
|
82
|
-
tempModule._compile(result.code, filePath);
|
|
83
|
-
return tempModule.exports;
|
|
84
|
-
} catch (esbuildError) {
|
|
85
|
-
console.warn("esbuild \u8F6C\u8BD1\u5931\u8D25\uFF0C\u5C1D\u8BD5\u7B80\u5355\u8F6C\u6362:", esbuildError);
|
|
86
|
-
const code = await fs.promises.readFile(filePath, "utf-8");
|
|
87
|
-
const jsCode = code.replace(/export\s+default\s+/, "module.exports = ").replace(/import\s+.*?from\s+['"][^'"]*['"];?\s*/g, "").replace(/:\s*[^=,})\]]+/g, "");
|
|
88
|
-
const tempModule = new import_node_module.Module(filePath);
|
|
89
|
-
tempModule.filename = filePath;
|
|
90
|
-
tempModule.paths = import_node_module.Module._nodeModulePaths(path.dirname(filePath));
|
|
91
|
-
tempModule._compile(jsCode, filePath);
|
|
92
|
-
return tempModule.exports;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
if (filePath.endsWith(".js") || filePath.endsWith(".mjs")) {
|
|
96
|
-
const fileUrl = (0, import_node_url.pathToFileURL)(filePath).href;
|
|
97
|
-
return import(`${fileUrl}?t=${Date.now()}`);
|
|
98
|
-
}
|
|
99
|
-
throw new Error(`\u4E0D\u652F\u6301\u7684\u914D\u7F6E\u6587\u4EF6\u7C7B\u578B: ${filePath}`);
|
|
100
|
-
}
|
|
101
|
-
async function loadCustomConfig() {
|
|
102
|
-
const cwd = process.cwd();
|
|
103
|
-
for (const configFile of CONFIG_FILES) {
|
|
104
|
-
const configPath = path.resolve(cwd, configFile);
|
|
105
|
-
if (fs.existsSync(configPath)) {
|
|
106
|
-
try {
|
|
107
|
-
const configModule = await loadConfigFile(configPath);
|
|
108
|
-
const configFunction = configModule.default || configModule;
|
|
109
|
-
if (typeof configFunction === "function") {
|
|
110
|
-
return configFunction;
|
|
111
|
-
} else {
|
|
112
|
-
console.warn(`\u914D\u7F6E\u6587\u4EF6 ${configFile} \u5FC5\u987B\u9ED8\u8BA4\u5BFC\u51FA\u4E00\u4E2A\u51FD\u6570`);
|
|
113
|
-
}
|
|
114
|
-
} catch (error) {
|
|
115
|
-
if (configFile.endsWith(".ts")) {
|
|
116
|
-
console.error(`\u52A0\u8F7DTypeScript\u914D\u7F6E\u6587\u4EF6 ${configFile} \u5931\u8D25:`, error);
|
|
117
|
-
console.log("\u63D0\u793A\uFF1A\u786E\u4FDD\u4F60\u7684\u9879\u76EE\u652F\u6301TypeScript\uFF0C\u6216\u8005\u4F7F\u7528 .js/.mjs \u914D\u7F6E\u6587\u4EF6");
|
|
118
|
-
} else {
|
|
119
|
-
console.error(`\u52A0\u8F7D\u914D\u7F6E\u6587\u4EF6 ${configFile} \u5931\u8D25:`, error);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
var fs, path, import_node_url, import_node_module, CONFIG_FILES;
|
|
127
|
-
var init_config_loader = __esm({
|
|
128
|
-
"src/config-loader.ts"() {
|
|
129
|
-
"use strict";
|
|
130
|
-
init_cjs_shims();
|
|
131
|
-
fs = __toESM(require("fs"));
|
|
132
|
-
path = __toESM(require("path"));
|
|
133
|
-
import_node_url = require("url");
|
|
134
|
-
import_node_module = require("module");
|
|
135
|
-
CONFIG_FILES = [
|
|
136
|
-
"multipage.config.js",
|
|
137
|
-
"multipage.config.mjs",
|
|
138
|
-
"multipage.config.ts"
|
|
139
|
-
];
|
|
140
|
-
}
|
|
141
|
-
});
|
|
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
|
-
|
|
193
41
|
// src/file-filter.ts
|
|
194
42
|
function filterEntryFiles(files, entry, exclude, _log) {
|
|
195
43
|
const result = [];
|
|
196
44
|
const nameToFile = /* @__PURE__ */ new Map();
|
|
197
45
|
let basePattern = entry.replace(/\/\*.*$/, "");
|
|
198
46
|
if (!basePattern || basePattern === entry) {
|
|
199
|
-
basePattern =
|
|
47
|
+
basePattern = path.dirname(entry.split("*")[0]);
|
|
200
48
|
}
|
|
201
49
|
const candidateFiles = [];
|
|
202
50
|
for (const file of files) {
|
|
203
51
|
if (exclude.includes(file)) {
|
|
204
52
|
continue;
|
|
205
53
|
}
|
|
206
|
-
const relativePath =
|
|
207
|
-
const pathParts = relativePath.split(
|
|
54
|
+
const relativePath = path.relative(basePattern, file);
|
|
55
|
+
const pathParts = relativePath.split(path.sep);
|
|
208
56
|
if (pathParts.length === 1) {
|
|
209
57
|
const fileName = pathParts[0];
|
|
210
|
-
const name =
|
|
58
|
+
const name = path.basename(fileName, path.extname(fileName));
|
|
211
59
|
candidateFiles.push({ name, file, priority: 1 });
|
|
212
60
|
} else if (pathParts.length >= 2) {
|
|
213
|
-
const fileName =
|
|
61
|
+
const fileName = path.basename(file, path.extname(file));
|
|
214
62
|
const dirName = pathParts[0];
|
|
215
63
|
if (fileName === "main") {
|
|
216
64
|
candidateFiles.push({ name: dirName, file, priority: 2 });
|
|
@@ -232,12 +80,12 @@ function filterEntryFiles(files, entry, exclude, _log) {
|
|
|
232
80
|
}
|
|
233
81
|
return result;
|
|
234
82
|
}
|
|
235
|
-
var
|
|
83
|
+
var path;
|
|
236
84
|
var init_file_filter = __esm({
|
|
237
85
|
"src/file-filter.ts"() {
|
|
238
86
|
"use strict";
|
|
239
87
|
init_cjs_shims();
|
|
240
|
-
|
|
88
|
+
path = __toESM(require("path"));
|
|
241
89
|
}
|
|
242
90
|
});
|
|
243
91
|
|
|
@@ -334,7 +182,7 @@ function generateBuildConfig(options) {
|
|
|
334
182
|
const pageContext = {
|
|
335
183
|
pageName: entryFile.name,
|
|
336
184
|
filePath: entryFile.file,
|
|
337
|
-
relativePath:
|
|
185
|
+
relativePath: path2.relative(process.cwd(), entryFile.file)
|
|
338
186
|
};
|
|
339
187
|
const pageConfig = getPageConfig(pageConfigs, pageContext, log);
|
|
340
188
|
const strategyName = (pageConfig == null ? void 0 : pageConfig.strategy) || "default";
|
|
@@ -415,7 +263,7 @@ function generateStrategyConfig(strategyName, pages, entryFiles, strategyConfig,
|
|
|
415
263
|
const pageContext = {
|
|
416
264
|
pageName,
|
|
417
265
|
filePath: entryFile.file,
|
|
418
|
-
relativePath:
|
|
266
|
+
relativePath: path2.relative(process.cwd(), entryFile.file),
|
|
419
267
|
strategy: strategyName
|
|
420
268
|
};
|
|
421
269
|
const pageConfig = getPageConfig(pageConfigs, pageContext, log);
|
|
@@ -424,17 +272,17 @@ function generateStrategyConfig(strategyName, pages, entryFiles, strategyConfig,
|
|
|
424
272
|
}
|
|
425
273
|
let templatePath = defaultTemplate;
|
|
426
274
|
const pageSpecificTemplate = `${pageName}.html`;
|
|
427
|
-
if (
|
|
275
|
+
if (fs.existsSync(path2.resolve(process.cwd(), pageSpecificTemplate))) {
|
|
428
276
|
templatePath = pageSpecificTemplate;
|
|
429
277
|
} else if (pageConfig == null ? void 0 : pageConfig.template) {
|
|
430
278
|
templatePath = pageConfig.template;
|
|
431
279
|
}
|
|
432
|
-
const templateFullPath =
|
|
433
|
-
if (!
|
|
280
|
+
const templateFullPath = path2.resolve(process.cwd(), templatePath);
|
|
281
|
+
if (!fs.existsSync(templateFullPath)) {
|
|
434
282
|
log(`\u8B66\u544A: \u6A21\u677F\u6587\u4EF6\u4E0D\u5B58\u5728: ${templatePath}`);
|
|
435
283
|
continue;
|
|
436
284
|
}
|
|
437
|
-
let templateContent =
|
|
285
|
+
let templateContent = fs.readFileSync(templateFullPath, "utf-8");
|
|
438
286
|
if (templateContent.includes(placeholder)) {
|
|
439
287
|
const entryPath = `./${entryFile.file}`;
|
|
440
288
|
templateContent = templateContent.replace(
|
|
@@ -442,8 +290,8 @@ function generateStrategyConfig(strategyName, pages, entryFiles, strategyConfig,
|
|
|
442
290
|
entryPath
|
|
443
291
|
);
|
|
444
292
|
}
|
|
445
|
-
const tempHtmlPath =
|
|
446
|
-
|
|
293
|
+
const tempHtmlPath = path2.resolve(process.cwd(), `.temp.mp.${pageName}.html`);
|
|
294
|
+
fs.writeFileSync(tempHtmlPath, templateContent);
|
|
447
295
|
tempFiles.push(tempHtmlPath);
|
|
448
296
|
htmlInputs[pageName] = tempHtmlPath;
|
|
449
297
|
}
|
|
@@ -486,22 +334,22 @@ function getViteOutputDirectory(viteBuildArgs = []) {
|
|
|
486
334
|
const outDirIndex = viteBuildArgs.findIndex((arg) => arg === "--outDir");
|
|
487
335
|
if (outDirIndex !== -1 && outDirIndex + 1 < viteBuildArgs.length) {
|
|
488
336
|
const outDir = viteBuildArgs[outDirIndex + 1];
|
|
489
|
-
return
|
|
337
|
+
return path2.resolve(process.cwd(), outDir);
|
|
490
338
|
}
|
|
491
339
|
const outDirArg = viteBuildArgs.find((arg) => arg.startsWith("--outDir="));
|
|
492
340
|
if (outDirArg) {
|
|
493
341
|
const outDir = outDirArg.split("=")[1];
|
|
494
|
-
return
|
|
342
|
+
return path2.resolve(process.cwd(), outDir);
|
|
495
343
|
}
|
|
496
|
-
return
|
|
344
|
+
return path2.resolve(process.cwd(), "dist");
|
|
497
345
|
}
|
|
498
346
|
function cleanViteOutputDirectory(viteBuildArgs = []) {
|
|
499
347
|
const outputDir = getViteOutputDirectory(viteBuildArgs);
|
|
500
348
|
const log = createLogger(true);
|
|
501
349
|
try {
|
|
502
|
-
if (
|
|
503
|
-
|
|
504
|
-
log(`\u{1F9F9} \u6E05\u7406\u8F93\u51FA\u76EE\u5F55: ${
|
|
350
|
+
if (fs.existsSync(outputDir)) {
|
|
351
|
+
fs.rmSync(outputDir, { recursive: true, force: true });
|
|
352
|
+
log(`\u{1F9F9} \u6E05\u7406\u8F93\u51FA\u76EE\u5F55: ${path2.relative(process.cwd(), outputDir)}`);
|
|
505
353
|
}
|
|
506
354
|
} catch (error) {
|
|
507
355
|
log(`\u26A0\uFE0F \u6E05\u7406\u8F93\u51FA\u76EE\u5F55\u5931\u8D25: ${outputDir}`, error);
|
|
@@ -521,7 +369,7 @@ function getAvailableStrategies(options) {
|
|
|
521
369
|
const pageContext = {
|
|
522
370
|
pageName: entryFile.name,
|
|
523
371
|
filePath: entryFile.file,
|
|
524
|
-
relativePath:
|
|
372
|
+
relativePath: path2.relative(process.cwd(), entryFile.file)
|
|
525
373
|
};
|
|
526
374
|
const pageConfig = getPageConfig(pageConfigs, pageContext, log);
|
|
527
375
|
const strategyName = (pageConfig == null ? void 0 : pageConfig.strategy) || "default";
|
|
@@ -533,21 +381,173 @@ function getAvailableStrategies(options) {
|
|
|
533
381
|
return ["default"];
|
|
534
382
|
}
|
|
535
383
|
}
|
|
536
|
-
var import_vite, import_glob,
|
|
384
|
+
var import_vite, import_glob, path2, fs;
|
|
537
385
|
var init_build_config = __esm({
|
|
538
386
|
"src/build-config.ts"() {
|
|
539
387
|
"use strict";
|
|
540
388
|
init_cjs_shims();
|
|
541
389
|
import_vite = require("vite");
|
|
542
390
|
import_glob = require("glob");
|
|
543
|
-
|
|
544
|
-
|
|
391
|
+
path2 = __toESM(require("path"));
|
|
392
|
+
fs = __toESM(require("fs"));
|
|
545
393
|
init_file_filter();
|
|
546
394
|
init_page_config();
|
|
547
395
|
init_utils();
|
|
548
396
|
}
|
|
549
397
|
});
|
|
550
398
|
|
|
399
|
+
// src/config-loader.ts
|
|
400
|
+
var config_loader_exports = {};
|
|
401
|
+
__export(config_loader_exports, {
|
|
402
|
+
hasCustomConfig: () => hasCustomConfig,
|
|
403
|
+
loadUserConfig: () => loadUserConfig
|
|
404
|
+
});
|
|
405
|
+
function hasCustomConfig() {
|
|
406
|
+
for (const filename of CONFIG_FILES) {
|
|
407
|
+
const configPath = path3.resolve(process.cwd(), filename);
|
|
408
|
+
if (fs2.existsSync(configPath)) {
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
return false;
|
|
413
|
+
}
|
|
414
|
+
async function loadUserConfig(context) {
|
|
415
|
+
const customConfig = await loadCustomConfig();
|
|
416
|
+
if (customConfig) {
|
|
417
|
+
const result = customConfig(context);
|
|
418
|
+
if (!result) {
|
|
419
|
+
return {};
|
|
420
|
+
}
|
|
421
|
+
return result;
|
|
422
|
+
}
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
async function loadConfigFile(filePath) {
|
|
426
|
+
if (filePath.endsWith(".ts")) {
|
|
427
|
+
try {
|
|
428
|
+
const code = await fs2.promises.readFile(filePath, "utf-8");
|
|
429
|
+
const esbuild = await import("esbuild");
|
|
430
|
+
const result = await esbuild.transform(code, {
|
|
431
|
+
loader: "ts",
|
|
432
|
+
format: "cjs",
|
|
433
|
+
// 使用 CommonJS 格式便于使用 Module._compile
|
|
434
|
+
target: "node16",
|
|
435
|
+
sourcemap: false
|
|
436
|
+
});
|
|
437
|
+
const tempModule = new import_node_module.Module(filePath);
|
|
438
|
+
tempModule.filename = filePath;
|
|
439
|
+
tempModule.paths = import_node_module.Module._nodeModulePaths(path3.dirname(filePath));
|
|
440
|
+
tempModule._compile(result.code, filePath);
|
|
441
|
+
return tempModule.exports;
|
|
442
|
+
} catch (esbuildError) {
|
|
443
|
+
console.warn("esbuild \u8F6C\u8BD1\u5931\u8D25\uFF0C\u5C1D\u8BD5\u7B80\u5355\u8F6C\u6362:", esbuildError);
|
|
444
|
+
const code = await fs2.promises.readFile(filePath, "utf-8");
|
|
445
|
+
const jsCode = code.replace(/export\s+default\s+/, "module.exports = ").replace(/import\s+.*?from\s+['"][^'"]*['"];?\s*/g, "").replace(/:\s*[^=,})\]]+/g, "");
|
|
446
|
+
const tempModule = new import_node_module.Module(filePath);
|
|
447
|
+
tempModule.filename = filePath;
|
|
448
|
+
tempModule.paths = import_node_module.Module._nodeModulePaths(path3.dirname(filePath));
|
|
449
|
+
tempModule._compile(jsCode, filePath);
|
|
450
|
+
return tempModule.exports;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
if (filePath.endsWith(".js") || filePath.endsWith(".mjs")) {
|
|
454
|
+
const fileUrl = (0, import_node_url.pathToFileURL)(filePath).href;
|
|
455
|
+
return import(`${fileUrl}?t=${Date.now()}`);
|
|
456
|
+
}
|
|
457
|
+
throw new Error(`\u4E0D\u652F\u6301\u7684\u914D\u7F6E\u6587\u4EF6\u7C7B\u578B: ${filePath}`);
|
|
458
|
+
}
|
|
459
|
+
async function loadCustomConfig() {
|
|
460
|
+
const cwd = process.cwd();
|
|
461
|
+
for (const configFile of CONFIG_FILES) {
|
|
462
|
+
const configPath = path3.resolve(cwd, configFile);
|
|
463
|
+
if (fs2.existsSync(configPath)) {
|
|
464
|
+
try {
|
|
465
|
+
const configModule = await loadConfigFile(configPath);
|
|
466
|
+
const configFunction = configModule.default || configModule;
|
|
467
|
+
if (typeof configFunction === "function") {
|
|
468
|
+
return configFunction;
|
|
469
|
+
} else {
|
|
470
|
+
console.warn(`\u914D\u7F6E\u6587\u4EF6 ${configFile} \u5FC5\u987B\u9ED8\u8BA4\u5BFC\u51FA\u4E00\u4E2A\u51FD\u6570`);
|
|
471
|
+
}
|
|
472
|
+
} catch (error) {
|
|
473
|
+
if (configFile.endsWith(".ts")) {
|
|
474
|
+
console.error(`\u52A0\u8F7DTypeScript\u914D\u7F6E\u6587\u4EF6 ${configFile} \u5931\u8D25:`, error);
|
|
475
|
+
console.log("\u63D0\u793A\uFF1A\u786E\u4FDD\u4F60\u7684\u9879\u76EE\u652F\u6301TypeScript\uFF0C\u6216\u8005\u4F7F\u7528 .js/.mjs \u914D\u7F6E\u6587\u4EF6");
|
|
476
|
+
} else {
|
|
477
|
+
console.error(`\u52A0\u8F7D\u914D\u7F6E\u6587\u4EF6 ${configFile} \u5931\u8D25:`, error);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
return null;
|
|
483
|
+
}
|
|
484
|
+
var fs2, path3, import_node_url, import_node_module, CONFIG_FILES;
|
|
485
|
+
var init_config_loader = __esm({
|
|
486
|
+
"src/config-loader.ts"() {
|
|
487
|
+
"use strict";
|
|
488
|
+
init_cjs_shims();
|
|
489
|
+
fs2 = __toESM(require("fs"));
|
|
490
|
+
path3 = __toESM(require("path"));
|
|
491
|
+
import_node_url = require("url");
|
|
492
|
+
import_node_module = require("module");
|
|
493
|
+
CONFIG_FILES = [
|
|
494
|
+
"multipage.config.js",
|
|
495
|
+
"multipage.config.mjs",
|
|
496
|
+
"multipage.config.ts"
|
|
497
|
+
];
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
// src/defaults.ts
|
|
502
|
+
var defaults_exports = {};
|
|
503
|
+
__export(defaults_exports, {
|
|
504
|
+
DEFAULT_CONFIG: () => DEFAULT_CONFIG,
|
|
505
|
+
isEmptyConfig: () => isEmptyConfig,
|
|
506
|
+
mergeWithDefaults: () => mergeWithDefaults
|
|
507
|
+
});
|
|
508
|
+
function mergeWithDefaults(userConfig) {
|
|
509
|
+
if (!userConfig) {
|
|
510
|
+
return { ...DEFAULT_CONFIG };
|
|
511
|
+
}
|
|
512
|
+
return {
|
|
513
|
+
entry: userConfig.entry ?? DEFAULT_CONFIG.entry,
|
|
514
|
+
exclude: userConfig.exclude ?? DEFAULT_CONFIG.exclude,
|
|
515
|
+
template: userConfig.template ?? DEFAULT_CONFIG.template,
|
|
516
|
+
placeholder: userConfig.placeholder ?? DEFAULT_CONFIG.placeholder,
|
|
517
|
+
debug: userConfig.debug ?? DEFAULT_CONFIG.debug,
|
|
518
|
+
strategies: userConfig.strategies ?? DEFAULT_CONFIG.strategies,
|
|
519
|
+
pageConfigs: userConfig.pageConfigs ?? DEFAULT_CONFIG.pageConfigs,
|
|
520
|
+
__forceBuildStrategy: userConfig.__forceBuildStrategy
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
function isEmptyConfig(config) {
|
|
524
|
+
if (Object.keys(config).length === 0) {
|
|
525
|
+
return true;
|
|
526
|
+
}
|
|
527
|
+
const hasValidEntry = config.entry && config.entry !== DEFAULT_CONFIG.entry;
|
|
528
|
+
const hasValidStrategies = config.strategies && Object.keys(config.strategies).length > 0;
|
|
529
|
+
const hasValidPageConfigs = config.pageConfigs && (typeof config.pageConfigs === "function" || Object.keys(config.pageConfigs).length > 0);
|
|
530
|
+
return !hasValidEntry && !hasValidStrategies && !hasValidPageConfigs;
|
|
531
|
+
}
|
|
532
|
+
var DEFAULT_CONFIG;
|
|
533
|
+
var init_defaults = __esm({
|
|
534
|
+
"src/defaults.ts"() {
|
|
535
|
+
"use strict";
|
|
536
|
+
init_cjs_shims();
|
|
537
|
+
DEFAULT_CONFIG = {
|
|
538
|
+
entry: "src/pages/**/*.{ts,js}",
|
|
539
|
+
exclude: [],
|
|
540
|
+
template: "index.html",
|
|
541
|
+
placeholder: "{{ENTRY_FILE}}",
|
|
542
|
+
debug: false,
|
|
543
|
+
strategies: {
|
|
544
|
+
default: {}
|
|
545
|
+
},
|
|
546
|
+
pageConfigs: {}
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
|
|
551
551
|
// src/cli.ts
|
|
552
552
|
var cli_exports = {};
|
|
553
553
|
__export(cli_exports, {
|
|
@@ -559,6 +559,7 @@ var import_node_child_process = require("child_process");
|
|
|
559
559
|
var fs3 = __toESM(require("fs"));
|
|
560
560
|
var path4 = __toESM(require("path"));
|
|
561
561
|
var glob2 = __toESM(require("glob"));
|
|
562
|
+
init_build_config();
|
|
562
563
|
function parseArgs() {
|
|
563
564
|
const args = process.argv.slice(2);
|
|
564
565
|
const viteBuildArgs = [];
|
|
@@ -635,19 +636,18 @@ function buildStrategy(strategy, viteBuildArgs, debug) {
|
|
|
635
636
|
}
|
|
636
637
|
child.on("close", (code) => {
|
|
637
638
|
const success = code === 0;
|
|
638
|
-
const
|
|
639
|
+
const actualOutputDir = getViteOutputDirectory(viteBuildArgs);
|
|
639
640
|
if (success) {
|
|
640
641
|
log(`\u2705 \u7B56\u7565 ${strategy} \u6784\u5EFA\u6210\u529F`);
|
|
641
642
|
try {
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
const files = fs3.readdirSync(outputPath);
|
|
643
|
+
if (fs3.existsSync(actualOutputDir)) {
|
|
644
|
+
const files = fs3.readdirSync(actualOutputDir);
|
|
645
645
|
for (const file of files) {
|
|
646
646
|
if (file.startsWith(".temp.mp.") && file.endsWith(".html")) {
|
|
647
|
-
const oldPath = path4.resolve(
|
|
647
|
+
const oldPath = path4.resolve(actualOutputDir, file);
|
|
648
648
|
const name = file.replace(/^\.temp\.mp\./, "").replace(/\.html$/, "");
|
|
649
649
|
const newName = `${name}.html`;
|
|
650
|
-
const newPath = path4.resolve(
|
|
650
|
+
const newPath = path4.resolve(actualOutputDir, newName);
|
|
651
651
|
fs3.renameSync(oldPath, newPath);
|
|
652
652
|
log(`\u91CD\u547D\u540DHTML: ${file} -> ${newName}`);
|
|
653
653
|
}
|
|
@@ -666,16 +666,17 @@ function buildStrategy(strategy, viteBuildArgs, debug) {
|
|
|
666
666
|
strategy,
|
|
667
667
|
success,
|
|
668
668
|
error: success ? void 0 : errorOutput || `\u6784\u5EFA\u5931\u8D25\uFF0C\u9000\u51FA\u7801: ${code}`,
|
|
669
|
-
outputDir
|
|
669
|
+
outputDir: actualOutputDir
|
|
670
670
|
});
|
|
671
671
|
});
|
|
672
672
|
child.on("error", (error) => {
|
|
673
673
|
log(`\u274C \u7B56\u7565 ${strategy} \u6784\u5EFA\u51FA\u9519:`, error.message);
|
|
674
|
+
const actualOutputDir = getViteOutputDirectory(viteBuildArgs);
|
|
674
675
|
resolve4({
|
|
675
676
|
strategy,
|
|
676
677
|
success: false,
|
|
677
678
|
error: error.message,
|
|
678
|
-
outputDir:
|
|
679
|
+
outputDir: actualOutputDir
|
|
679
680
|
});
|
|
680
681
|
});
|
|
681
682
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fchc8/vite-plugin-multi-page",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.1",
|
|
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",
|