@meng-xi/vite-plugin 0.0.7 → 0.0.9
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 +790 -404
- package/README.md +788 -403
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/plugins/index.cjs +1 -1
- package/dist/plugins/index.d.cts +764 -2
- package/dist/plugins/index.d.mts +764 -2
- package/dist/plugins/index.d.ts +764 -2
- package/dist/plugins/index.mjs +1 -1
- package/dist/shared/vite-plugin.BI4kA-bR.mjs +526 -0
- package/dist/shared/vite-plugin.CsdNNQ-4.cjs +526 -0
- package/package.json +72 -72
- package/dist/shared/vite-plugin.CIahO6bu.mjs +0 -37
- package/dist/shared/vite-plugin.DqgHJjxa.cjs +0 -37
package/README-en.md
CHANGED
|
@@ -1,404 +1,790 @@
|
|
|
1
|
-
**English** | [中文](./README.md)
|
|
2
|
-
|
|
3
|
-
<div align="center">
|
|
4
|
-
<a href="https://github.com/MengXi-Studio/vite-plugin">
|
|
5
|
-
<img alt="MengXi Studio Logo" width="215" src="https://github.com/MengXi-Studio/vite-plugin/blob/master/packages/docs/src/public/logo.png">
|
|
6
|
-
</a>
|
|
7
|
-
<br>
|
|
8
|
-
<h1>@meng-xi/vite-plugin</h1>
|
|
9
|
-
<p>A toolkit providing practical plugins for Vite, also a complete plugin development framework</p>
|
|
10
|
-
|
|
11
|
-
[](LICENSE) [](https://www.npmjs.com/package/@meng-xi/vite-plugin)
|
|
12
|
-

|
|
13
|
-
|
|
14
|
-
</div>
|
|
15
|
-
|
|
16
|
-
## Features
|
|
17
|
-
|
|
18
|
-
- **Ready to Use** - Provides
|
|
19
|
-
|
|
20
|
-
- **
|
|
21
|
-
- **
|
|
22
|
-
- **
|
|
23
|
-
- **
|
|
24
|
-
- **
|
|
25
|
-
|
|
26
|
-
## Documentation
|
|
27
|
-
|
|
28
|
-
View full documentation: [https://mengxi-studio.github.io/vite-plugin/](https://mengxi-studio.github.io/vite-plugin/)
|
|
29
|
-
|
|
30
|
-
## Installation
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
import type {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
import {
|
|
105
|
-
import type {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
export const myPlugin = createPluginFactory(MyPlugin)
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
|
153
|
-
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
|
178
|
-
|
|
|
179
|
-
| `
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
|
188
|
-
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
|
261
|
-
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
|
266
|
-
|
|
|
267
|
-
|
|
|
268
|
-
|
|
|
269
|
-
|
|
|
270
|
-
|
|
|
271
|
-
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
//
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
//
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
|
309
|
-
|
|
|
310
|
-
|
|
|
311
|
-
|
|
|
312
|
-
|
|
|
313
|
-
|
|
|
314
|
-
|
|
|
315
|
-
|
|
|
316
|
-
|
|
|
317
|
-
|
|
|
318
|
-
|
|
|
319
|
-
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
|
326
|
-
|
|
|
327
|
-
|
|
|
328
|
-
|
|
|
329
|
-
|
|
|
330
|
-
|
|
|
331
|
-
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
| Option
|
|
343
|
-
|
|
|
344
|
-
|
|
|
345
|
-
|
|
|
346
|
-
|
|
|
347
|
-
|
|
|
348
|
-
|
|
|
349
|
-
|
|
350
|
-
`
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
|
355
|
-
|
|
|
356
|
-
|
|
|
357
|
-
|
|
|
358
|
-
|
|
359
|
-
`
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
1
|
+
**English** | [中文](./README.md)
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
<a href="https://github.com/MengXi-Studio/vite-plugin">
|
|
5
|
+
<img alt="MengXi Studio Logo" width="215" src="https://github.com/MengXi-Studio/vite-plugin/blob/master/packages/docs/src/public/logo.png">
|
|
6
|
+
</a>
|
|
7
|
+
<br>
|
|
8
|
+
<h1>@meng-xi/vite-plugin</h1>
|
|
9
|
+
<p>A toolkit providing practical plugins for Vite, also a complete plugin development framework</p>
|
|
10
|
+
|
|
11
|
+
[](LICENSE) [](https://www.npmjs.com/package/@meng-xi/vite-plugin)
|
|
12
|
+

|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
- **Ready to Use** - Provides 6 practical plugins covering build progress display, file copying, router generation, version management, icon injection, and global Loading state management
|
|
19
|
+
- **Plugin Development Framework** - Exports core components like BasePlugin, Logger, Validator for building custom Vite plugins
|
|
20
|
+
- **Complete Lifecycle** - Supports initialization, config resolution, destroy lifecycle management with automatic hook composition
|
|
21
|
+
- **Type Safe** - Complete TypeScript type definitions with configuration validators ensuring parameter correctness
|
|
22
|
+
- **Flexible Configuration** - All plugins support detailed configuration to meet diverse scenario requirements
|
|
23
|
+
- **Safe Execution** - Built-in error handling strategies (throw / log / ignore) for unified exception management
|
|
24
|
+
- **On-demand Import** - Supports sub-path exports to reduce bundle size
|
|
25
|
+
|
|
26
|
+
## Documentation
|
|
27
|
+
|
|
28
|
+
View full documentation: [https://mengxi-studio.github.io/vite-plugin/](https://mengxi-studio.github.io/vite-plugin/)
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# npm
|
|
34
|
+
npm install @meng-xi/vite-plugin -D
|
|
35
|
+
|
|
36
|
+
# yarn
|
|
37
|
+
yarn add @meng-xi/vite-plugin -D
|
|
38
|
+
|
|
39
|
+
# pnpm
|
|
40
|
+
pnpm add @meng-xi/vite-plugin -D
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
### Using Built-in Plugins
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { defineConfig } from 'vite'
|
|
49
|
+
import { buildProgress, copyFile, generateRouter, generateVersion, injectIco, injectLoading } from '@meng-xi/vite-plugin'
|
|
50
|
+
|
|
51
|
+
export default defineConfig({
|
|
52
|
+
plugins: [
|
|
53
|
+
// Build progress bar
|
|
54
|
+
buildProgress(),
|
|
55
|
+
|
|
56
|
+
// Copy files
|
|
57
|
+
copyFile({
|
|
58
|
+
sourceDir: 'src/assets',
|
|
59
|
+
targetDir: 'dist/assets'
|
|
60
|
+
}),
|
|
61
|
+
|
|
62
|
+
// Generate router config (uni-app)
|
|
63
|
+
generateRouter({
|
|
64
|
+
pagesJsonPath: 'src/pages.json',
|
|
65
|
+
outputPath: 'src/router.config.ts'
|
|
66
|
+
}),
|
|
67
|
+
|
|
68
|
+
// Generate version
|
|
69
|
+
generateVersion({
|
|
70
|
+
format: 'datetime',
|
|
71
|
+
outputType: 'both'
|
|
72
|
+
}),
|
|
73
|
+
|
|
74
|
+
// Inject website icon (supports string shorthand)
|
|
75
|
+
injectIco('/assets'),
|
|
76
|
+
|
|
77
|
+
// Inject global Loading
|
|
78
|
+
injectLoading({
|
|
79
|
+
defaultVisible: true,
|
|
80
|
+
autoHideOn: 'DOMContentLoaded'
|
|
81
|
+
})
|
|
82
|
+
]
|
|
83
|
+
})
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Accessing Plugin Instance
|
|
87
|
+
|
|
88
|
+
All built-in plugins return an object with a `pluginInstance` property for accessing internal state:
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
import type { PluginWithInstance } from '@meng-xi/vite-plugin/factory'
|
|
92
|
+
import type { GenerateRouterOptions } from '@meng-xi/vite-plugin'
|
|
93
|
+
|
|
94
|
+
const routerPlugin = generateRouter({ watch: true }) as PluginWithInstance<GenerateRouterOptions>
|
|
95
|
+
|
|
96
|
+
// Access plugin internals via pluginInstance
|
|
97
|
+
console.log(routerPlugin.pluginInstance?.options)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Developing Custom Plugins
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { BasePlugin, createPluginFactory } from '@meng-xi/vite-plugin'
|
|
104
|
+
import type { BasePluginOptions, PluginWithInstance } from '@meng-xi/vite-plugin/factory'
|
|
105
|
+
import type { Plugin } from 'vite'
|
|
106
|
+
|
|
107
|
+
interface MyPluginOptions extends BasePluginOptions {
|
|
108
|
+
path: string
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
class MyPlugin extends BasePlugin<MyPluginOptions> {
|
|
112
|
+
protected getDefaultOptions() {
|
|
113
|
+
return { path: './default' }
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
protected validateOptions(): void {
|
|
117
|
+
this.validator.field('path').required().string().validate()
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
protected getPluginName(): string {
|
|
121
|
+
return 'my-plugin'
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
protected addPluginHooks(plugin: Plugin): void {
|
|
125
|
+
plugin.buildStart = () => {
|
|
126
|
+
this.logger.info(`Plugin started with path: ${this.options.path}`)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
protected destroy(): void {
|
|
131
|
+
super.destroy()
|
|
132
|
+
// Custom cleanup logic, e.g. close connections, stop watchers
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Basic usage
|
|
137
|
+
export const myPlugin = createPluginFactory(MyPlugin)
|
|
138
|
+
|
|
139
|
+
// With normalizer (supports shorthand string config)
|
|
140
|
+
export const myPluginWithNormalizer = createPluginFactory(MyPlugin, opt => (typeof opt === 'string' ? { path: opt } : opt))
|
|
141
|
+
// Usage with shorthand: myPluginWithNormalizer('./custom-path')
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Plugin Development Framework
|
|
145
|
+
|
|
146
|
+
### BasePlugin Core Concepts
|
|
147
|
+
|
|
148
|
+
`BasePlugin` is the base class for all plugins, providing complete lifecycle management and development conventions:
|
|
149
|
+
|
|
150
|
+
#### Lifecycle
|
|
151
|
+
|
|
152
|
+
| Phase | Method | Description |
|
|
153
|
+
| ----------------- | ------------------ | -------------------------------------------------------------- |
|
|
154
|
+
| Initialization | `constructor` | Merge options, initialize logger and validator |
|
|
155
|
+
| Config Resolution | `onConfigResolved` | Called when Vite config is resolved |
|
|
156
|
+
| Hook Registration | `addPluginHooks` | Register Vite plugin hooks |
|
|
157
|
+
| Destroy | `destroy` | Automatically called during `closeBundle` for resource cleanup |
|
|
158
|
+
|
|
159
|
+
#### Automatic Hook Composition
|
|
160
|
+
|
|
161
|
+
The `toPlugin()` method automatically composes the following hooks:
|
|
162
|
+
|
|
163
|
+
- **configResolved** - Base class `onConfigResolved` runs first, then subclass hook
|
|
164
|
+
- **closeBundle** - Subclass hook runs first, then base class `destroy`
|
|
165
|
+
|
|
166
|
+
> Subclasses don't need to manually register `closeBundle` hooks for cleanup — just override the `destroy()` method.
|
|
167
|
+
|
|
168
|
+
#### Required Methods
|
|
169
|
+
|
|
170
|
+
| Method | Description |
|
|
171
|
+
| ------------------------ | --------------------- |
|
|
172
|
+
| `getPluginName()` | Return plugin name |
|
|
173
|
+
| `addPluginHooks(plugin)` | Add Vite plugin hooks |
|
|
174
|
+
|
|
175
|
+
#### Optional Methods
|
|
176
|
+
|
|
177
|
+
| Method | Default Behavior | Description |
|
|
178
|
+
| -------------------------- | ----------------- | ------------------------------------------- |
|
|
179
|
+
| `getDefaultOptions()` | Returns `{}` | Provide plugin default options |
|
|
180
|
+
| `validateOptions()` | No validation | Validate configuration parameters |
|
|
181
|
+
| `getEnforce()` | `undefined` | Plugin execution order (`'pre'` / `'post'`) |
|
|
182
|
+
| `onConfigResolved(config)` | Store config | Config resolved callback |
|
|
183
|
+
| `destroy()` | Unregister logger | Cleanup logic when plugin is destroyed |
|
|
184
|
+
|
|
185
|
+
#### Built-in Properties
|
|
186
|
+
|
|
187
|
+
| Property | Type | Description |
|
|
188
|
+
| ------------ | ------------------------ | ----------------------------- |
|
|
189
|
+
| `options` | `Required<T>` | Merged complete configuration |
|
|
190
|
+
| `logger` | `PluginLogger` | Plugin logger |
|
|
191
|
+
| `validator` | `Validator<T>` | Configuration validator |
|
|
192
|
+
| `viteConfig` | `ResolvedConfig \| null` | Resolved Vite configuration |
|
|
193
|
+
|
|
194
|
+
#### Error Handling Strategy
|
|
195
|
+
|
|
196
|
+
Control error behavior via the `errorStrategy` configuration option:
|
|
197
|
+
|
|
198
|
+
- `'throw'` (default) - Log error and throw exception, halting the build
|
|
199
|
+
- `'log'` - Log error but don't throw, continue execution
|
|
200
|
+
- `'ignore'` - Log error but don't throw, continue execution
|
|
201
|
+
|
|
202
|
+
Wrap error-prone operations with `safeExecute` / `safeExecuteSync`:
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
// Async safe execution
|
|
206
|
+
const result = await this.safeExecute(async () => {
|
|
207
|
+
return await someAsyncOperation()
|
|
208
|
+
}, 'Execute async operation')
|
|
209
|
+
|
|
210
|
+
// Sync safe execution
|
|
211
|
+
const value = this.safeExecuteSync(() => {
|
|
212
|
+
return someSyncOperation()
|
|
213
|
+
}, 'Execute sync operation')
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### createPluginFactory
|
|
217
|
+
|
|
218
|
+
Create plugin factory functions with optional normalizer support:
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
// Basic usage
|
|
222
|
+
const myPlugin = createPluginFactory(MyPlugin)
|
|
223
|
+
|
|
224
|
+
// With normalizer (supports shorthand string config)
|
|
225
|
+
const myPlugin = createPluginFactory(MyPlugin, opt => (typeof opt === 'string' ? { path: opt } : opt))
|
|
226
|
+
|
|
227
|
+
// Usage with shorthand
|
|
228
|
+
myPlugin('./custom-path')
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Validator
|
|
232
|
+
|
|
233
|
+
Fluent configuration validator with chainable API:
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
import { Validator } from '@meng-xi/vite-plugin/common'
|
|
237
|
+
|
|
238
|
+
const validator = new Validator(options)
|
|
239
|
+
validator
|
|
240
|
+
.field('sourceDir')
|
|
241
|
+
.required()
|
|
242
|
+
.string()
|
|
243
|
+
.field('targetDir')
|
|
244
|
+
.required()
|
|
245
|
+
.string()
|
|
246
|
+
.field('overwrite')
|
|
247
|
+
.boolean()
|
|
248
|
+
.default(true)
|
|
249
|
+
.field('port')
|
|
250
|
+
.number()
|
|
251
|
+
.field('list')
|
|
252
|
+
.array()
|
|
253
|
+
.field('config')
|
|
254
|
+
.object()
|
|
255
|
+
.field('name')
|
|
256
|
+
.custom(val => val.length > 0, 'name cannot be empty')
|
|
257
|
+
.validate()
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
| Method | Description |
|
|
261
|
+
| ------------ | --------------------------------------------------------------- |
|
|
262
|
+
| `field()` | Specify the field to validate |
|
|
263
|
+
| `required()` | Mark field as required |
|
|
264
|
+
| `string()` | Validate field value is a string type |
|
|
265
|
+
| `boolean()` | Validate field value is a boolean type |
|
|
266
|
+
| `number()` | Validate field value is a number type |
|
|
267
|
+
| `array()` | Validate field value is an array type |
|
|
268
|
+
| `object()` | Validate field value is an object type |
|
|
269
|
+
| `default()` | Set default value for field (only when value is undefined/null) |
|
|
270
|
+
| `custom()` | Validate field value with a custom function |
|
|
271
|
+
| `validate()` | Execute validation, throws error on failure |
|
|
272
|
+
|
|
273
|
+
### Logger
|
|
274
|
+
|
|
275
|
+
Global singleton log manager providing independent log control for each plugin:
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
import { Logger } from '@meng-xi/vite-plugin/logger'
|
|
279
|
+
|
|
280
|
+
// Create logger (usually called automatically by BasePlugin)
|
|
281
|
+
Logger.create({ name: 'my-plugin', enabled: true })
|
|
282
|
+
|
|
283
|
+
// Unregister plugin log config (automatically called on plugin destroy)
|
|
284
|
+
Logger.unregister('my-plugin')
|
|
285
|
+
|
|
286
|
+
// Destroy singleton (for test scenarios)
|
|
287
|
+
Logger.destroy()
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Log output format:
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
ℹ️ [@meng-xi/vite-plugin:my-plugin] Info message
|
|
294
|
+
✅ [@meng-xi/vite-plugin:my-plugin] Success message
|
|
295
|
+
⚠️ [@meng-xi/vite-plugin:my-plugin] Warning message
|
|
296
|
+
❌ [@meng-xi/vite-plugin:my-plugin] Error message
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Common Utilities
|
|
300
|
+
|
|
301
|
+
Exported via `@meng-xi/vite-plugin/common`, reusable in custom plugins:
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
import { deepMerge, formatDate, parseTemplate, toCamelCase, toPascalCase, stripJsonComments, generateRandomHash, Validator } from '@meng-xi/vite-plugin/common'
|
|
305
|
+
import { readFileContent, writeFileContent, fileExists, copySourceToTarget } from '@meng-xi/vite-plugin/common'
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
| Function | Description |
|
|
309
|
+
| ---------------------- | --------------------------------------------------------------- |
|
|
310
|
+
| `deepMerge()` | Deep merge objects (undefined skipped, arrays overwritten) |
|
|
311
|
+
| `formatDate()` | Format date with `{YYYY}`, `{MM}`, `{DD}` etc. placeholders |
|
|
312
|
+
| `parseTemplate()` | Parse template string, replace placeholders |
|
|
313
|
+
| `toCamelCase()` | Convert to camelCase |
|
|
314
|
+
| `toPascalCase()` | Convert to PascalCase |
|
|
315
|
+
| `stripJsonComments()` | Remove comments from JSON string |
|
|
316
|
+
| `generateRandomHash()` | Generate random hash string (1-64 characters) |
|
|
317
|
+
| `readFileContent()` | Async read file content |
|
|
318
|
+
| `writeFileContent()` | Async write file content |
|
|
319
|
+
| `fileExists()` | Async check if file exists |
|
|
320
|
+
| `copySourceToTarget()` | Copy files or directories with incremental copy and concurrency |
|
|
321
|
+
|
|
322
|
+
## Built-in Plugins
|
|
323
|
+
|
|
324
|
+
| Plugin | Description |
|
|
325
|
+
| --------------- | ----------------------------------------------------------------------------------------- |
|
|
326
|
+
| buildProgress | Real-time build progress bar in terminal, supports bar / spinner / minimal |
|
|
327
|
+
| copyFile | Copy files or directories after build, supports incremental copying |
|
|
328
|
+
| generateRouter | Auto-generate router config from pages.json (uni-app) |
|
|
329
|
+
| generateVersion | Auto-generate version numbers, supports file output and global variable injection |
|
|
330
|
+
| injectIco | Inject website icon links into HTML files, supports string shorthand config |
|
|
331
|
+
| injectLoading | Inject global Loading state management with request interception and white-screen Loading |
|
|
332
|
+
|
|
333
|
+
### buildProgress
|
|
334
|
+
|
|
335
|
+
Display real-time build progress bar in terminal during Vite build, supporting three display formats.
|
|
336
|
+
|
|
337
|
+
**Progress calculation logic:**
|
|
338
|
+
|
|
339
|
+
1. config phase (5%) → resolve phase (10%) → transform phase (15%-85%, by module conversion ratio) → bundle phase (+10%) → write phase (+5%) → done (100%)
|
|
340
|
+
2. Non-TTY terminal environments (e.g. CI/CD) automatically degrade to log output mode
|
|
341
|
+
|
|
342
|
+
| Option | Type | Default | Description |
|
|
343
|
+
| --------------- | ------------------------------------- | ------- | ---------------------------------------------------- |
|
|
344
|
+
| width | `number` | `30` | Progress bar width (characters) |
|
|
345
|
+
| format | `'bar'` \| `'spinner'` \| `'minimal'` | `'bar'` | Progress bar display format |
|
|
346
|
+
| completeChar | `string` | `'█'` | Fill character for completed portion |
|
|
347
|
+
| incompleteChar | `string` | `'░'` | Fill character for incomplete portion |
|
|
348
|
+
| clearOnComplete | `boolean` | `true` | Whether to clear progress bar on build completion |
|
|
349
|
+
| showModuleName | `boolean` | `true` | Whether to show the currently processing module name |
|
|
350
|
+
| theme | `ProgressTheme` | - | Custom color theme |
|
|
351
|
+
|
|
352
|
+
**ProgressTheme**
|
|
353
|
+
|
|
354
|
+
| Property | Type | Description |
|
|
355
|
+
| --------------- | -------------------------- | ------------------------ |
|
|
356
|
+
| completeColor | `(text: string) => string` | Completed portion color |
|
|
357
|
+
| incompleteColor | `(text: string) => string` | Incomplete portion color |
|
|
358
|
+
| percentageColor | `(text: string) => string` | Percentage number color |
|
|
359
|
+
| phaseColor | `(text: string) => string` | Phase label color |
|
|
360
|
+
| moduleColor | `(text: string) => string` | Module name color |
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
// Default bar format
|
|
364
|
+
buildProgress()
|
|
365
|
+
|
|
366
|
+
// Spinner format
|
|
367
|
+
buildProgress({ format: 'spinner' })
|
|
368
|
+
|
|
369
|
+
// Minimal format
|
|
370
|
+
buildProgress({ format: 'minimal' })
|
|
371
|
+
|
|
372
|
+
// Custom appearance
|
|
373
|
+
buildProgress({
|
|
374
|
+
width: 40,
|
|
375
|
+
completeChar: '■',
|
|
376
|
+
incompleteChar: '□',
|
|
377
|
+
clearOnComplete: false
|
|
378
|
+
})
|
|
379
|
+
|
|
380
|
+
// Custom color theme
|
|
381
|
+
buildProgress({
|
|
382
|
+
theme: {
|
|
383
|
+
completeColor: t => `\x1b[32m${t}\x1b[39m`,
|
|
384
|
+
incompleteColor: t => `\x1b[90m${t}\x1b[39m`,
|
|
385
|
+
percentageColor: t => `\x1b[1m${t}\x1b[22m`,
|
|
386
|
+
phaseColor: t => `\x1b[36m${t}\x1b[39m`,
|
|
387
|
+
moduleColor: t => `\x1b[90m${t}\x1b[39m`
|
|
388
|
+
}
|
|
389
|
+
})
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### copyFile
|
|
393
|
+
|
|
394
|
+
Copy files or directories to specified locations after Vite build is completed, with `enforce: 'post'`.
|
|
395
|
+
|
|
396
|
+
| Option | Type | Default | Description |
|
|
397
|
+
| ----------- | --------- | ------- | ------------------------------------------ |
|
|
398
|
+
| sourceDir | `string` | - | Source directory path (required) |
|
|
399
|
+
| targetDir | `string` | - | Target directory path (required) |
|
|
400
|
+
| overwrite | `boolean` | `true` | Whether to overwrite existing files |
|
|
401
|
+
| recursive | `boolean` | `true` | Whether to recursively copy subdirectories |
|
|
402
|
+
| incremental | `boolean` | `true` | Whether to enable incremental copying |
|
|
403
|
+
|
|
404
|
+
```typescript
|
|
405
|
+
// Basic usage
|
|
406
|
+
copyFile({
|
|
407
|
+
sourceDir: 'src/assets',
|
|
408
|
+
targetDir: 'dist/assets'
|
|
409
|
+
})
|
|
410
|
+
|
|
411
|
+
// Disable overwrite and incremental copy
|
|
412
|
+
copyFile({
|
|
413
|
+
sourceDir: 'src/static',
|
|
414
|
+
targetDir: 'dist/static',
|
|
415
|
+
overwrite: false,
|
|
416
|
+
incremental: false
|
|
417
|
+
})
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### generateRouter
|
|
421
|
+
|
|
422
|
+
Automatically generate router configuration files based on uni-app project's `pages.json`.
|
|
423
|
+
|
|
424
|
+
| Option | Type | Default | Description |
|
|
425
|
+
| -------------------- | --------------------------------------------------------- | ------------------------ | ------------------------------------------------ |
|
|
426
|
+
| pagesJsonPath | `string` | `'src/pages.json'` | Path to pages.json file |
|
|
427
|
+
| outputPath | `string` | `'src/router.config.ts'` | Output file path |
|
|
428
|
+
| outputFormat | `'ts'` \| `'js'` | `'ts'` | Output file format |
|
|
429
|
+
| nameStrategy | `'path'` \| `'camelCase'` \| `'pascalCase'` \| `'custom'` | `'camelCase'` | Route name strategy |
|
|
430
|
+
| customNameGenerator | `(path: string) => string` | - | Custom route name generator function |
|
|
431
|
+
| includeSubPackages | `boolean` | `true` | Whether to include sub-package routes |
|
|
432
|
+
| watch | `boolean` | `true` | Whether to watch changes and auto-regenerate |
|
|
433
|
+
| metaMapping | `Record<string, string>` | - | Mapping from page style fields to meta |
|
|
434
|
+
| exportTypes | `boolean` | `true` | Whether to export type definitions |
|
|
435
|
+
| preserveRouteChanges | `boolean` | `true` | Whether to preserve user modifications to routes |
|
|
436
|
+
|
|
437
|
+
> Default `metaMapping` is `{ navigationBarTitleText: 'title', requireAuth: 'requireAuth' }`, automatically mapping page style fields to route meta. When `nameStrategy` is `'custom'`, `customNameGenerator` must be
|
|
438
|
+
> provided.
|
|
439
|
+
|
|
440
|
+
```typescript
|
|
441
|
+
// Basic usage
|
|
442
|
+
generateRouter()
|
|
443
|
+
|
|
444
|
+
// Custom pages.json path
|
|
445
|
+
generateRouter({ pagesJsonPath: 'pages.json' })
|
|
446
|
+
|
|
447
|
+
// Output JavaScript file
|
|
448
|
+
generateRouter({ outputFormat: 'js', outputPath: 'src/router.config.js' })
|
|
449
|
+
|
|
450
|
+
// PascalCase naming strategy
|
|
451
|
+
generateRouter({ nameStrategy: 'pascalCase' })
|
|
452
|
+
|
|
453
|
+
// Custom route name generator
|
|
454
|
+
generateRouter({
|
|
455
|
+
nameStrategy: 'custom',
|
|
456
|
+
customNameGenerator: path => `route_${path.replace(/\//g, '_')}`
|
|
457
|
+
})
|
|
458
|
+
|
|
459
|
+
// Custom meta mapping
|
|
460
|
+
generateRouter({
|
|
461
|
+
metaMapping: {
|
|
462
|
+
navigationBarTitleText: 'title',
|
|
463
|
+
requireAuth: 'requireAuth',
|
|
464
|
+
customField: 'custom'
|
|
465
|
+
}
|
|
466
|
+
})
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### generateVersion
|
|
470
|
+
|
|
471
|
+
Automatically generate version numbers during the Vite build process.
|
|
472
|
+
|
|
473
|
+
| Option | Type | Default | Description |
|
|
474
|
+
| ------------ | --------------------------------------------------------------------------------- | ------------------- | ------------------------------ |
|
|
475
|
+
| format | `'timestamp'` \| `'date'` \| `'datetime'` \| `'semver'` \| `'hash'` \| `'custom'` | `'timestamp'` | Version format |
|
|
476
|
+
| customFormat | `string` | - | Custom format template |
|
|
477
|
+
| semverBase | `string` | `'1.0.0'` | Semantic version base |
|
|
478
|
+
| outputType | `'file'` \| `'define'` \| `'both'` | `'file'` | Output type |
|
|
479
|
+
| outputFile | `string` | `'version.json'` | Output file path |
|
|
480
|
+
| defineName | `string` | `'__APP_VERSION__'` | Global variable name to inject |
|
|
481
|
+
| hashLength | `number` | `8` | Hash length (1-32) |
|
|
482
|
+
| prefix | `string` | - | Version number prefix |
|
|
483
|
+
| suffix | `string` | - | Version number suffix |
|
|
484
|
+
| extra | `Record<string, unknown>` | - | Extra info (JSON file only) |
|
|
485
|
+
|
|
486
|
+
**customFormat placeholders:**
|
|
487
|
+
|
|
488
|
+
| Placeholder | Description | Example |
|
|
489
|
+
| ------------- | ----------------------------------- | --------------- |
|
|
490
|
+
| `{YYYY}` | Four-digit year | `2026` |
|
|
491
|
+
| `{YY}` | Two-digit year | `26` |
|
|
492
|
+
| `{MM}` | Two-digit month | `05` |
|
|
493
|
+
| `{DD}` | Two-digit day | `22` |
|
|
494
|
+
| `{HH}` | Two-digit hour (24h) | `15` |
|
|
495
|
+
| `{mm}` | Two-digit minute | `30` |
|
|
496
|
+
| `{ss}` | Two-digit second | `00` |
|
|
497
|
+
| `{SSS}` | Three-digit millisecond | `123` |
|
|
498
|
+
| `{timestamp}` | Timestamp (milliseconds) | `1779464601000` |
|
|
499
|
+
| `{hash}` | Random hash | `a1b2c3d4` |
|
|
500
|
+
| `{major}` | Major version (requires semverBase) | `1` |
|
|
501
|
+
| `{minor}` | Minor version (requires semverBase) | `0` |
|
|
502
|
+
| `{patch}` | Patch version (requires semverBase) | `0` |
|
|
503
|
+
|
|
504
|
+
> When `format` is `'custom'`, `customFormat` must be provided. When `outputType` is `'define'` or `'both'`, a `{defineName}_INFO` global variable is also injected, containing complete info such as version, build time,
|
|
505
|
+
> and timestamp.
|
|
506
|
+
|
|
507
|
+
```typescript
|
|
508
|
+
// Timestamp format (default)
|
|
509
|
+
generateVersion()
|
|
510
|
+
|
|
511
|
+
// Date format
|
|
512
|
+
generateVersion({ format: 'date' })
|
|
513
|
+
|
|
514
|
+
// Semantic version format
|
|
515
|
+
generateVersion({ format: 'semver', semverBase: '2.0.0', prefix: 'v' })
|
|
516
|
+
|
|
517
|
+
// Custom format
|
|
518
|
+
generateVersion({
|
|
519
|
+
format: 'custom',
|
|
520
|
+
customFormat: '{YYYY}.{MM}.{DD}-{hash}',
|
|
521
|
+
hashLength: 6
|
|
522
|
+
})
|
|
523
|
+
|
|
524
|
+
// Inject into code
|
|
525
|
+
generateVersion({ outputType: 'define', defineName: '__VERSION__' })
|
|
526
|
+
|
|
527
|
+
// Both file output and code injection
|
|
528
|
+
generateVersion({
|
|
529
|
+
outputType: 'both',
|
|
530
|
+
outputFile: 'build-info.json',
|
|
531
|
+
defineName: '__BUILD_VERSION__',
|
|
532
|
+
extra: { environment: 'production' }
|
|
533
|
+
})
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### injectIco
|
|
537
|
+
|
|
538
|
+
Inject website icon links into the head of HTML files during the Vite build process. Supports string shorthand config.
|
|
539
|
+
|
|
540
|
+
| Option | Type | Default | Description |
|
|
541
|
+
| ----------- | -------- | ------- | ------------------------------- |
|
|
542
|
+
| base | `string` | `'/'` | Base path for icon files |
|
|
543
|
+
| url | `string` | - | Complete URL for the icon |
|
|
544
|
+
| link | `string` | - | Custom complete link tag HTML |
|
|
545
|
+
| icons | `Icon[]` | - | Custom icon array |
|
|
546
|
+
| copyOptions | `object` | - | Icon file copying configuration |
|
|
547
|
+
|
|
548
|
+
> Priority: `link` > `url` > `base`. When `link` is provided, custom HTML is injected directly; when `url` is provided, the complete URL is used; otherwise `base + '/favicon.ico'` is used.
|
|
549
|
+
|
|
550
|
+
`Icon` interface definition:
|
|
551
|
+
|
|
552
|
+
| Property | Type | Required | Description |
|
|
553
|
+
| -------- | -------- | -------- | ------------------ |
|
|
554
|
+
| rel | `string` | Yes | Icon relation type |
|
|
555
|
+
| href | `string` | Yes | Icon URL |
|
|
556
|
+
| sizes | `string` | No | Icon sizes |
|
|
557
|
+
| type | `string` | No | Icon MIME type |
|
|
558
|
+
|
|
559
|
+
`copyOptions` interface definition:
|
|
560
|
+
|
|
561
|
+
| Property | Type | Required | Default | Description |
|
|
562
|
+
| --------- | --------- | -------- | ------- | --------------------------- |
|
|
563
|
+
| sourceDir | `string` | Yes | - | Icon source directory |
|
|
564
|
+
| targetDir | `string` | Yes | - | Icon target directory |
|
|
565
|
+
| overwrite | `boolean` | No | `true` | Whether to overwrite files |
|
|
566
|
+
| recursive | `boolean` | No | `true` | Whether to copy recursively |
|
|
567
|
+
|
|
568
|
+
```typescript
|
|
569
|
+
// Use default config
|
|
570
|
+
injectIco()
|
|
571
|
+
|
|
572
|
+
// String shorthand (set base path)
|
|
573
|
+
injectIco('/assets')
|
|
574
|
+
|
|
575
|
+
// Custom icon array
|
|
576
|
+
injectIco({
|
|
577
|
+
base: '/assets',
|
|
578
|
+
icons: [
|
|
579
|
+
{ rel: 'icon', href: '/favicon.svg', type: 'image/svg+xml' },
|
|
580
|
+
{ rel: 'icon', href: '/favicon-32x32.png', sizes: '32x32', type: 'image/png' },
|
|
581
|
+
{ rel: 'apple-touch-icon', href: '/apple-touch-icon.png', sizes: '180x180' }
|
|
582
|
+
]
|
|
583
|
+
})
|
|
584
|
+
|
|
585
|
+
// Custom complete link tag
|
|
586
|
+
injectIco({
|
|
587
|
+
link: '<link rel="icon" href="/favicon.svg" type="image/svg+xml" />'
|
|
588
|
+
})
|
|
589
|
+
|
|
590
|
+
// With file copying
|
|
591
|
+
injectIco({
|
|
592
|
+
base: '/assets',
|
|
593
|
+
copyOptions: {
|
|
594
|
+
sourceDir: 'src/assets/icons',
|
|
595
|
+
targetDir: 'dist/assets/icons'
|
|
596
|
+
}
|
|
597
|
+
})
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
### injectLoading
|
|
601
|
+
|
|
602
|
+
Inject global Loading state management with XHR/Fetch request interception, white-screen Loading, custom styles, and lifecycle callbacks.
|
|
603
|
+
|
|
604
|
+
**Injection strategy:**
|
|
605
|
+
|
|
606
|
+
- `defaultVisible: false` (default): All code (CSS + HTML + JS) is dynamically injected via JS before `</body>`
|
|
607
|
+
- `defaultVisible: true`: CSS + HTML are injected as static tags before `</head>` (visible on white screen), JS is injected before `</body>`
|
|
608
|
+
|
|
609
|
+
| Option | Type | Default | Description |
|
|
610
|
+
| -------------- | ----------------------------------------------- | ----------------------- | ------------------------------------------------------- |
|
|
611
|
+
| position | `'center'` \| `'top'` \| `'bottom'` | `'center'` | Loading display position |
|
|
612
|
+
| defaultText | `string` | `'Loading...'` | Default display text |
|
|
613
|
+
| spinnerType | `'spinner'` \| `'dots'` \| `'pulse'` \| `'bar'` | `'spinner'` | Spinner icon type |
|
|
614
|
+
| style | `LoadingStyle` | - | Custom style configuration |
|
|
615
|
+
| transition | `TransitionConfig` | `{ enabled: true }` | Transition animation configuration |
|
|
616
|
+
| minDisplayTime | `MinDisplayTime` | `{ enabled: true }` | Minimum display time configuration |
|
|
617
|
+
| delayShow | `DelayShow` | `{ enabled: true }` | Delayed show configuration |
|
|
618
|
+
| debounceHide | `DebounceHide` | `{ enabled: false }` | Debounced hide configuration |
|
|
619
|
+
| autoBind | `'fetch'` \| `'xhr'` \| `'all'` \| `'none'` | `'none'` | Auto-bind request interception mode |
|
|
620
|
+
| requestFilter | `RequestFilter` | - | Request filter configuration |
|
|
621
|
+
| globalName | `string` | `'__LOADING_MANAGER__'` | Global variable name injected into browser |
|
|
622
|
+
| customTemplate | `string` | - | Custom HTML template (must include `data-loading-text`) |
|
|
623
|
+
| defaultVisible | `boolean` | `false` | Whether initially visible (white-screen Loading) |
|
|
624
|
+
| autoHideOn | `'DOMContentLoaded'` \| `'load'` \| `'manual'` | `'DOMContentLoaded'` | Auto-hide timing (requires `defaultVisible: true`) |
|
|
625
|
+
| callbacks | `LoadingCallbacks` | - | Lifecycle callbacks |
|
|
626
|
+
|
|
627
|
+
**LoadingStyle**
|
|
628
|
+
|
|
629
|
+
| Property | Type | Default | Description |
|
|
630
|
+
| ------------------ | --------- | ------------------------- | ---------------------------------------- |
|
|
631
|
+
| overlayColor | `string` | `'rgba(255,255,255,0.7)'` | Overlay background color |
|
|
632
|
+
| spinnerColor | `string` | `'#4361ee'` | Spinner icon color |
|
|
633
|
+
| spinnerSize | `string` | `'40px'` | Spinner icon size |
|
|
634
|
+
| textColor | `string` | `'#333'` | Text color |
|
|
635
|
+
| textSize | `string` | `'14px'` | Text size |
|
|
636
|
+
| customClass | `string` | - | Custom CSS class name |
|
|
637
|
+
| customStyle | `string` | - | Custom inline style |
|
|
638
|
+
| zIndex | `number` | `9999` | z-index value |
|
|
639
|
+
| pointerEvents | `boolean` | `true` | Whether to enable overlay pointer events |
|
|
640
|
+
| backdropBlur | `boolean` | `false` | Whether to enable backdrop blur |
|
|
641
|
+
| backdropBlurAmount | `number` | `4` | Backdrop blur amount (px) |
|
|
642
|
+
|
|
643
|
+
**TransitionConfig**
|
|
644
|
+
|
|
645
|
+
| Property | Type | Default | Description |
|
|
646
|
+
| -------- | --------- | ------------ | ---------------------------- |
|
|
647
|
+
| enabled | `boolean` | `true` | Whether to enable transition |
|
|
648
|
+
| duration | `number` | `200` | Transition duration (ms) |
|
|
649
|
+
| easing | `string` | `'ease-out'` | Easing function |
|
|
650
|
+
|
|
651
|
+
**MinDisplayTime**
|
|
652
|
+
|
|
653
|
+
| Property | Type | Default | Description |
|
|
654
|
+
| -------- | --------- | ------- | --------------------------------------------------------- |
|
|
655
|
+
| enabled | `boolean` | `true` | Whether to enable |
|
|
656
|
+
| duration | `number` | `300` | Minimum display time (ms), prevents Loading from flashing |
|
|
657
|
+
|
|
658
|
+
**DelayShow**
|
|
659
|
+
|
|
660
|
+
| Property | Type | Default | Description |
|
|
661
|
+
| -------- | --------- | ------- | ------------------------------------------------------------------------------ |
|
|
662
|
+
| enabled | `boolean` | `true` | Whether to enable |
|
|
663
|
+
| duration | `number` | `200` | Delay duration (ms); if request completes within this time, Loading won't show |
|
|
664
|
+
|
|
665
|
+
**DebounceHide**
|
|
666
|
+
|
|
667
|
+
| Property | Type | Default | Description |
|
|
668
|
+
| -------- | --------- | ------- | ----------------------- |
|
|
669
|
+
| enabled | `boolean` | `false` | Whether to enable |
|
|
670
|
+
| duration | `number` | `100` | Debounce wait time (ms) |
|
|
671
|
+
|
|
672
|
+
**RequestFilter**
|
|
673
|
+
|
|
674
|
+
| Property | Type | Description |
|
|
675
|
+
| ------------------ | ---------- | --------------------------------------------------------------------- |
|
|
676
|
+
| excludeUrls | `RegExp[]` | Array of URL regex patterns to exclude |
|
|
677
|
+
| includeUrls | `RegExp[]` | Array of URL regex patterns to include (higher priority than exclude) |
|
|
678
|
+
| excludeMethods | `string[]` | Array of HTTP methods to exclude |
|
|
679
|
+
| excludeUrlPrefixes | `string[]` | Array of URL prefixes to exclude (prefix matching, more efficient) |
|
|
680
|
+
|
|
681
|
+
**LoadingCallbacks**
|
|
682
|
+
|
|
683
|
+
Callbacks are provided as **function body strings** (injected into browser at build time, function references cannot be passed).
|
|
684
|
+
|
|
685
|
+
| Property | Type | Description |
|
|
686
|
+
| ------------ | -------- | ----------------------------------------------- |
|
|
687
|
+
| onBeforeShow | `string` | Before show callback, `return false` to prevent |
|
|
688
|
+
| onShow | `string` | After show callback |
|
|
689
|
+
| onBeforeHide | `string` | Before hide callback, `return false` to prevent |
|
|
690
|
+
| onHide | `string` | After hide callback |
|
|
691
|
+
| onDestroy | `string` | On destroy callback |
|
|
692
|
+
|
|
693
|
+
**LoadingManager API**
|
|
694
|
+
|
|
695
|
+
Access via `window.__LOADING_MANAGER__`:
|
|
696
|
+
|
|
697
|
+
| Method | Description |
|
|
698
|
+
| -------------------------- | ------------------------------------------------------------------- |
|
|
699
|
+
| `show(text?)` | Show Loading, optionally pass text |
|
|
700
|
+
| `hide()` | Hide Loading (subject to min display time and debounce constraints) |
|
|
701
|
+
| `forceHide()` | Force hide, ignoring min display time and debounce |
|
|
702
|
+
| `toggle(text?)` | Toggle Loading show/hide state |
|
|
703
|
+
| `updateText(text)` | Update text content |
|
|
704
|
+
| `isVisible()` | Get whether Loading is currently visible |
|
|
705
|
+
| `isPointerEventsEnabled()` | Get whether pointer events are currently enabled |
|
|
706
|
+
| `enablePointerEvents()` | Enable overlay pointer events, intercept all clicks and scrolls |
|
|
707
|
+
| `disablePointerEvents()` | Disable overlay pointer events, allow interaction passthrough |
|
|
708
|
+
| `togglePointerEvents()` | Toggle overlay pointer events state |
|
|
709
|
+
| `getPendingCount()` | Get the number of pending requests |
|
|
710
|
+
| `destroy()` | Destroy instance, clean up DOM and restore original interceptors |
|
|
711
|
+
|
|
712
|
+
```typescript
|
|
713
|
+
// White-screen Loading: visible on page load, auto-hide on DOMContentLoaded
|
|
714
|
+
injectLoading({ defaultVisible: true, autoHideOn: 'DOMContentLoaded' })
|
|
715
|
+
|
|
716
|
+
// White-screen Loading: auto-hide after all resources loaded
|
|
717
|
+
injectLoading({ defaultVisible: true, autoHideOn: 'load' })
|
|
718
|
+
|
|
719
|
+
// Vue/React SPA: visible on white screen, manually hide after framework renders
|
|
720
|
+
injectLoading({ defaultVisible: true, autoHideOn: 'manual' })
|
|
721
|
+
// In app entry: window.__LOADING_MANAGER__.hide()
|
|
722
|
+
|
|
723
|
+
// Auto-intercept all requests
|
|
724
|
+
injectLoading({ autoBind: 'all' })
|
|
725
|
+
|
|
726
|
+
// Custom styles + request filtering
|
|
727
|
+
injectLoading({
|
|
728
|
+
style: { overlayColor: 'rgba(0,0,0,0.5)', spinnerColor: '#fff', backdropBlur: true },
|
|
729
|
+
autoBind: 'fetch',
|
|
730
|
+
requestFilter: { excludeUrls: [/\/api\/health/], excludeUrlPrefixes: ['http://localhost'] }
|
|
731
|
+
})
|
|
732
|
+
|
|
733
|
+
// Debounced hide (prevent rapid flashing)
|
|
734
|
+
injectLoading({ debounceHide: { enabled: true, duration: 100 } })
|
|
735
|
+
|
|
736
|
+
// Lifecycle callbacks
|
|
737
|
+
injectLoading({
|
|
738
|
+
callbacks: {
|
|
739
|
+
onBeforeShow: 'if (shouldSkip) return false;',
|
|
740
|
+
onShow: 'console.log("loading shown")',
|
|
741
|
+
onBeforeHide: 'if (shouldKeepVisible) return false;',
|
|
742
|
+
onHide: 'console.log("loading hidden")'
|
|
743
|
+
}
|
|
744
|
+
})
|
|
745
|
+
|
|
746
|
+
// Manual control
|
|
747
|
+
injectLoading()
|
|
748
|
+
window.__LOADING_MANAGER__.show('Saving...')
|
|
749
|
+
window.__LOADING_MANAGER__.hide()
|
|
750
|
+
window.__LOADING_MANAGER__.toggle()
|
|
751
|
+
window.__LOADING_MANAGER__.disablePointerEvents()
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
## Sub-path Exports
|
|
755
|
+
|
|
756
|
+
Support importing modules on demand to reduce bundle size:
|
|
757
|
+
|
|
758
|
+
```typescript
|
|
759
|
+
// Full import
|
|
760
|
+
import { buildProgress, copyFile, injectLoading, BasePlugin, Logger } from '@meng-xi/vite-plugin'
|
|
761
|
+
|
|
762
|
+
// Module-level import
|
|
763
|
+
import { BasePlugin, createPluginFactory } from '@meng-xi/vite-plugin/factory'
|
|
764
|
+
import { Logger } from '@meng-xi/vite-plugin/logger'
|
|
765
|
+
import { buildProgress, copyFile, generateRouter, injectLoading } from '@meng-xi/vite-plugin/plugins'
|
|
766
|
+
import { Validator, readFileContent, writeFileContent } from '@meng-xi/vite-plugin/common'
|
|
767
|
+
|
|
768
|
+
// Type imports (on-demand type definitions from sub-paths)
|
|
769
|
+
import type { PluginWithInstance, PluginFactory, BasePluginOptions } from '@meng-xi/vite-plugin/factory'
|
|
770
|
+
import type { BuildProgressOptions, GenerateVersionOptions, InjectIcoOptions, InjectLoadingOptions, Icon } from '@meng-xi/vite-plugin/plugins'
|
|
771
|
+
import type { DateFormatOptions } from '@meng-xi/vite-plugin/common'
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
## Changelog
|
|
775
|
+
|
|
776
|
+
See [GitHub Releases](https://github.com/MengXi-Studio/vite-plugin/releases)
|
|
777
|
+
|
|
778
|
+
## Contributing
|
|
779
|
+
|
|
780
|
+
Contributions are welcome! Please follow these steps:
|
|
781
|
+
|
|
782
|
+
1. Fork the repository
|
|
783
|
+
2. Create a feature branch: `git checkout -b feature/your-feature`
|
|
784
|
+
3. Commit changes: `git commit -m "feat: your feature description"`
|
|
785
|
+
4. Push to branch: `git push origin feature/your-feature`
|
|
786
|
+
5. Create a Pull Request
|
|
787
|
+
|
|
788
|
+
## License
|
|
789
|
+
|
|
790
|
+
[MIT](LICENSE)
|