@meng-xi/vite-plugin 0.1.1 → 0.1.3
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 +522 -610
- package/README.md +496 -584
- package/dist/common/compress/index.cjs +1 -0
- package/dist/common/compress/index.d.cts +23 -0
- package/dist/common/compress/index.d.mts +23 -0
- package/dist/common/compress/index.d.ts +23 -0
- package/dist/common/compress/index.mjs +1 -0
- package/dist/common/format/index.cjs +1 -1
- package/dist/common/format/index.d.cts +33 -1
- package/dist/common/format/index.d.mts +33 -1
- package/dist/common/format/index.d.ts +33 -1
- package/dist/common/format/index.mjs +1 -1
- package/dist/common/fs/index.cjs +1 -1
- package/dist/common/fs/index.d.cts +70 -2
- package/dist/common/fs/index.d.mts +70 -2
- package/dist/common/fs/index.d.ts +70 -2
- package/dist/common/fs/index.mjs +1 -1
- package/dist/common/index.cjs +1 -1
- package/dist/common/index.d.cts +4 -2
- package/dist/common/index.d.mts +4 -2
- package/dist/common/index.d.ts +4 -2
- package/dist/common/index.mjs +1 -1
- package/dist/common/path/index.cjs +1 -0
- package/dist/common/path/index.d.cts +22 -0
- package/dist/common/path/index.d.mts +22 -0
- package/dist/common/path/index.d.ts +22 -0
- package/dist/common/path/index.mjs +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +6 -2
- package/dist/index.d.mts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.mjs +1 -1
- package/dist/plugins/bundleAnalyzer/index.cjs +235 -0
- package/dist/plugins/bundleAnalyzer/index.d.cts +215 -0
- package/dist/plugins/bundleAnalyzer/index.d.mts +215 -0
- package/dist/plugins/bundleAnalyzer/index.d.ts +215 -0
- package/dist/plugins/bundleAnalyzer/index.mjs +235 -0
- package/dist/plugins/compressAssets/index.cjs +1 -0
- package/dist/plugins/compressAssets/index.d.cts +132 -0
- package/dist/plugins/compressAssets/index.d.mts +132 -0
- package/dist/plugins/compressAssets/index.d.ts +132 -0
- package/dist/plugins/compressAssets/index.mjs +1 -0
- package/dist/plugins/generateRouter/index.cjs +4 -4
- package/dist/plugins/generateRouter/index.mjs +1 -1
- package/dist/plugins/generateVersion/index.cjs +1 -1
- package/dist/plugins/generateVersion/index.mjs +1 -1
- package/dist/plugins/htmlInject/index.cjs +7 -7
- package/dist/plugins/index.cjs +1 -1
- package/dist/plugins/index.d.cts +2 -0
- package/dist/plugins/index.d.mts +2 -0
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/index.mjs +1 -1
- package/dist/plugins/loadingManager/index.cjs +1 -1
- package/dist/plugins/loadingManager/index.mjs +1 -1
- package/package.json +24 -2
package/README.md
CHANGED
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
|
|
16
16
|
## 特性
|
|
17
17
|
|
|
18
|
-
- **开箱即用** - 提供
|
|
18
|
+
- **开箱即用** - 提供 10 个实用插件,覆盖构建进度展示、构建产物分析与压缩、文件复制、路由生成、版本管理、版本更新检查、HTML 注入、图标注入、全局 Loading 状态管理等常见场景
|
|
19
19
|
- **插件开发框架** - 导出 BasePlugin、Logger、Validator 等核心组件,快速构建符合规范的自定义 Vite 插件
|
|
20
|
+
- **通用工具库** - 内置 Common 工具模块,提供格式化、文件系统、压缩、路径处理、HTML 注入、对象操作、脚本生成、参数验证等可复用工具函数
|
|
20
21
|
- **完整生命周期** - 支持初始化、配置解析、销毁等生命周期管理,自动组合钩子逻辑
|
|
21
22
|
- **类型安全** - 完整的 TypeScript 类型定义,配置验证器确保参数正确性
|
|
22
23
|
- **灵活配置** - 所有插件支持详细配置,满足多样化场景需求
|
|
@@ -46,53 +47,22 @@ pnpm add @meng-xi/vite-plugin -D
|
|
|
46
47
|
|
|
47
48
|
```typescript
|
|
48
49
|
import { defineConfig } from 'vite'
|
|
49
|
-
import { buildProgress, copyFile, generateRouter, generateVersion, versionUpdateChecker, htmlInject, faviconManager, loadingManager } from '@meng-xi/vite-plugin'
|
|
50
|
+
import { buildProgress, bundleAnalyzer, compressAssets, copyFile, generateRouter, generateVersion, versionUpdateChecker, htmlInject, faviconManager, loadingManager } from '@meng-xi/vite-plugin'
|
|
50
51
|
|
|
51
52
|
export default defineConfig({
|
|
52
53
|
plugins: [
|
|
53
|
-
// 构建进度条
|
|
54
54
|
buildProgress(),
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
copyFile({
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}),
|
|
61
|
-
|
|
62
|
-
// 生成路由配置(uni-app)
|
|
63
|
-
generateRouter({
|
|
64
|
-
pagesJsonPath: 'src/pages.json',
|
|
65
|
-
outputPath: 'src/router.config.ts'
|
|
66
|
-
}),
|
|
67
|
-
|
|
68
|
-
// 生成版本号
|
|
69
|
-
generateVersion({
|
|
70
|
-
format: 'datetime',
|
|
71
|
-
outputType: 'both'
|
|
72
|
-
}),
|
|
73
|
-
|
|
74
|
-
// 版本更新检查(配合 generateVersion 使用)
|
|
55
|
+
bundleAnalyzer({ outputFormat: 'both', sizeThreshold: 200 }),
|
|
56
|
+
compressAssets({ algorithm: 'gzip' }),
|
|
57
|
+
copyFile({ sourceDir: 'src/assets', targetDir: 'dist/assets' }),
|
|
58
|
+
generateRouter({ pagesJsonPath: 'src/pages.json', outputPath: 'src/router.config.ts' }),
|
|
59
|
+
generateVersion({ format: 'datetime', outputType: 'both' }),
|
|
75
60
|
versionUpdateChecker(),
|
|
76
|
-
|
|
77
|
-
// HTML 内容注入
|
|
78
61
|
htmlInject({
|
|
79
|
-
rules: [
|
|
80
|
-
{
|
|
81
|
-
id: 'meta-description',
|
|
82
|
-
content: '<meta name="description" content="My App">',
|
|
83
|
-
position: 'head-end'
|
|
84
|
-
}
|
|
85
|
-
]
|
|
62
|
+
rules: [{ id: 'meta-description', content: '<meta name="description" content="My App">', position: 'head-end' }]
|
|
86
63
|
}),
|
|
87
|
-
|
|
88
|
-
// 注入网站图标(支持字符串简写)
|
|
89
64
|
faviconManager('/assets'),
|
|
90
|
-
|
|
91
|
-
// 全局 Loading 状态管理
|
|
92
|
-
loadingManager({
|
|
93
|
-
defaultVisible: true,
|
|
94
|
-
autoHideOn: 'DOMContentLoaded'
|
|
95
|
-
})
|
|
65
|
+
loadingManager({ defaultVisible: true, autoHideOn: 'DOMContentLoaded' })
|
|
96
66
|
]
|
|
97
67
|
})
|
|
98
68
|
```
|
|
@@ -106,23 +76,25 @@ import type { PluginWithInstance } from '@meng-xi/vite-plugin/factory'
|
|
|
106
76
|
import type { GenerateRouterOptions } from '@meng-xi/vite-plugin'
|
|
107
77
|
|
|
108
78
|
const routerPlugin = generateRouter({ watch: true }) as PluginWithInstance<GenerateRouterOptions>
|
|
109
|
-
|
|
110
|
-
// 通过 pluginInstance 访问插件内部
|
|
111
79
|
console.log(routerPlugin.pluginInstance?.options)
|
|
112
80
|
```
|
|
113
81
|
|
|
114
82
|
## 内置插件
|
|
115
83
|
|
|
116
|
-
| 插件 | 说明
|
|
117
|
-
| -------------------- |
|
|
118
|
-
| buildProgress | 终端实时构建进度条,支持 bar / spinner / minimal
|
|
119
|
-
|
|
|
120
|
-
|
|
|
121
|
-
|
|
|
122
|
-
|
|
|
123
|
-
|
|
|
124
|
-
|
|
|
125
|
-
|
|
|
84
|
+
| 插件 | 说明 |
|
|
85
|
+
| -------------------- | --------------------------------------------------------------------- |
|
|
86
|
+
| buildProgress | 终端实时构建进度条,支持 bar / spinner / minimal |
|
|
87
|
+
| bundleAnalyzer | 构建产物体积分析,支持 JSON/HTML 报告、gzip 计算、阈值告警和构建对比 |
|
|
88
|
+
| compressAssets | 构建产物压缩,支持 gzip / brotli / both,并发压缩和统计报告 |
|
|
89
|
+
| copyFile | 构建完成后复制文件或目录,支持增量复制 |
|
|
90
|
+
| generateRouter | 根据 pages.json 自动生成路由配置(uni-app) |
|
|
91
|
+
| generateVersion | 自动生成版本号,支持文件输出和全局变量注入 |
|
|
92
|
+
| versionUpdateChecker | 运行时版本更新检查,支持多种提示样式和自定义回调 |
|
|
93
|
+
| htmlInject | HTML 内容注入,支持多种位置、选择器定位、条件注入、模板变量和安全过滤 |
|
|
94
|
+
| faviconManager | 管理网站图标链接注入和文件复制,支持字符串简写配置 |
|
|
95
|
+
| loadingManager | 全局 Loading 状态管理,支持请求拦截、防抖、过渡动画和白屏 Loading |
|
|
96
|
+
|
|
97
|
+
---
|
|
126
98
|
|
|
127
99
|
### buildProgress
|
|
128
100
|
|
|
@@ -154,24 +126,10 @@ console.log(routerPlugin.pluginInstance?.options)
|
|
|
154
126
|
| moduleColor | `(text: string) => string` | 模块名称颜色 |
|
|
155
127
|
|
|
156
128
|
```typescript
|
|
157
|
-
// 默认进度条格式
|
|
158
129
|
buildProgress()
|
|
159
|
-
|
|
160
|
-
// 旋转动画格式
|
|
161
130
|
buildProgress({ format: 'spinner' })
|
|
162
|
-
|
|
163
|
-
// 精简格式
|
|
164
131
|
buildProgress({ format: 'minimal' })
|
|
165
|
-
|
|
166
|
-
// 自定义外观
|
|
167
|
-
buildProgress({
|
|
168
|
-
width: 40,
|
|
169
|
-
completeChar: '■',
|
|
170
|
-
incompleteChar: '□',
|
|
171
|
-
clearOnComplete: false
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
// 自定义颜色主题
|
|
132
|
+
buildProgress({ width: 40, completeChar: '■', incompleteChar: '□', clearOnComplete: false })
|
|
175
133
|
buildProgress({
|
|
176
134
|
theme: {
|
|
177
135
|
completeColor: t => `\x1b[32m${t}\x1b[39m`,
|
|
@@ -183,6 +141,73 @@ buildProgress({
|
|
|
183
141
|
})
|
|
184
142
|
```
|
|
185
143
|
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
### bundleAnalyzer
|
|
147
|
+
|
|
148
|
+
在 Vite 构建完成后自动分析输出目录中的构建产物,生成体积统计、模块排行、文件类型分布等关键指标,支持 JSON 报告和 HTML 可视化图表。
|
|
149
|
+
|
|
150
|
+
**核心功能:**
|
|
151
|
+
|
|
152
|
+
- 扫描构建输出目录,分析 chunk、模块和资源文件
|
|
153
|
+
- 计算原始大小和 gzip 压缩大小
|
|
154
|
+
- 按文件类型统计体积分布
|
|
155
|
+
- Top N 大模块排行
|
|
156
|
+
- 体积阈值告警(超过阈值 2 倍标记为 critical)
|
|
157
|
+
- 与上次构建结果对比,生成差异报告
|
|
158
|
+
- HTML 报告支持 treemap / sunburst / list 三种可视化图表
|
|
159
|
+
|
|
160
|
+
| 选项 | 类型 | 默认值 | 描述 |
|
|
161
|
+
| ------------------ | --------------------------------------- | ------------------- | ---------------------------------------- |
|
|
162
|
+
| outputFormat | `'json'` \| `'html'` \| `'both'` | `'json'` | 报告输出格式 |
|
|
163
|
+
| outputFile | `string` | `'bundle-analysis'` | 报告输出文件名(不含扩展名) |
|
|
164
|
+
| openAnalyzer | `boolean` | `false` | 是否在生成 HTML 报告后自动打开浏览器 |
|
|
165
|
+
| sizeThreshold | `number` | `100` | 体积告警阈值(KB) |
|
|
166
|
+
| topModules | `number` | `20` | Top N 大模块排行数量 |
|
|
167
|
+
| gzipSize | `boolean` | `true` | 是否计算 gzip 大小 |
|
|
168
|
+
| excludeNodeModules | `boolean` | `false` | 是否排除 node_modules 中的模块 |
|
|
169
|
+
| excludePatterns | `string[]` | `[]` | 需要排除的文件路径模式列表 |
|
|
170
|
+
| includeExtensions | `string[]` | `[]` | 需要包含的文件扩展名列表,为空则包含所有 |
|
|
171
|
+
| compareWith | `string` \| `null` | `null` | 用于对比的之前分析报告路径 |
|
|
172
|
+
| defaultChartType | `'treemap'` \| `'sunburst'` \| `'list'` | `'treemap'` | HTML 报告中图表的默认展示形式 |
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
bundleAnalyzer()
|
|
176
|
+
bundleAnalyzer({ outputFormat: 'both', openAnalyzer: true })
|
|
177
|
+
bundleAnalyzer({ sizeThreshold: 200, topModules: 30, gzipSize: true })
|
|
178
|
+
bundleAnalyzer({ compareWith: 'dist/bundle-analysis.json', defaultChartType: 'sunburst' })
|
|
179
|
+
bundleAnalyzer({ excludeNodeModules: true, includeExtensions: ['.js', '.css'] })
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
### compressAssets
|
|
185
|
+
|
|
186
|
+
在 Vite 构建完成后自动压缩输出目录中的文件,支持 gzip 和 brotli 两种压缩算法。
|
|
187
|
+
|
|
188
|
+
| 选项 | 类型 | 默认值 | 描述 |
|
|
189
|
+
| ------------------ | ---------------------------------- | ----------------------------------------------------------- | ------------------------------ |
|
|
190
|
+
| algorithm | `'gzip'` \| `'brotli'` \| `'both'` | `'gzip'` | 压缩算法 |
|
|
191
|
+
| threshold | `number` | `1024` | 最小压缩阈值(字节) |
|
|
192
|
+
| deleteOriginalFile | `boolean` | `false` | 压缩后是否删除原始文件 |
|
|
193
|
+
| includeExtensions | `string[]` | `['.js', '.css', '.html', '.svg', '.json', '.xml', '.txt']` | 需要压缩的文件扩展名 |
|
|
194
|
+
| excludeExtensions | `string[]` | `[]` | 需要排除的文件扩展名 |
|
|
195
|
+
| excludePaths | `string[]` | `[]` | 需要排除的路径前缀 |
|
|
196
|
+
| compressionLevel | `number` | `9` | gzip 压缩级别(1-9) |
|
|
197
|
+
| brotliQuality | `number` | `11` | brotli 压缩质量(1-11) |
|
|
198
|
+
| reportOutput | `string` \| `false` | `'compress-report.json'` | 压缩报告输出路径,false 不生成 |
|
|
199
|
+
| parallelLimit | `number` | `10` | 并发压缩最大文件数 |
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
compressAssets()
|
|
203
|
+
compressAssets({ algorithm: 'brotli' })
|
|
204
|
+
compressAssets({ algorithm: 'both', threshold: 2048, compressionLevel: 9, brotliQuality: 11 })
|
|
205
|
+
compressAssets({ deleteOriginalFile: true, reportOutput: 'compress-report.json' })
|
|
206
|
+
compressAssets({ includeExtensions: ['.js', '.css'], excludePaths: ['assets/images'], parallelLimit: 5 })
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
186
211
|
### copyFile
|
|
187
212
|
|
|
188
213
|
在 Vite 构建完成后复制文件或目录到指定位置,执行时机为 `enforce: 'post'`。
|
|
@@ -196,21 +221,12 @@ buildProgress({
|
|
|
196
221
|
| incremental | `boolean` | `true` | 是否启用增量复制 |
|
|
197
222
|
|
|
198
223
|
```typescript
|
|
199
|
-
|
|
200
|
-
copyFile({
|
|
201
|
-
sourceDir: 'src/assets',
|
|
202
|
-
targetDir: 'dist/assets'
|
|
203
|
-
})
|
|
204
|
-
|
|
205
|
-
// 禁用覆盖和增量复制
|
|
206
|
-
copyFile({
|
|
207
|
-
sourceDir: 'src/static',
|
|
208
|
-
targetDir: 'dist/static',
|
|
209
|
-
overwrite: false,
|
|
210
|
-
incremental: false
|
|
211
|
-
})
|
|
224
|
+
copyFile({ sourceDir: 'src/assets', targetDir: 'dist/assets' })
|
|
225
|
+
copyFile({ sourceDir: 'src/static', targetDir: 'dist/static', overwrite: false, incremental: false })
|
|
212
226
|
```
|
|
213
227
|
|
|
228
|
+
---
|
|
229
|
+
|
|
214
230
|
### generateRouter
|
|
215
231
|
|
|
216
232
|
根据 uni-app 项目的 `pages.json` 自动生成路由配置文件。
|
|
@@ -228,37 +244,19 @@ copyFile({
|
|
|
228
244
|
| exportTypes | `boolean` | `true` | 是否导出类型定义 |
|
|
229
245
|
| preserveRouteChanges | `boolean` | `true` | 是否保留用户对 routes 的修改 |
|
|
230
246
|
|
|
231
|
-
> 默认 `metaMapping` 为 `{ navigationBarTitleText: 'title', requireAuth: 'requireAuth' }
|
|
247
|
+
> 默认 `metaMapping` 为 `{ navigationBarTitleText: 'title', requireAuth: 'requireAuth' }`。当 `nameStrategy` 为 `'custom'` 时,必须提供 `customNameGenerator`。
|
|
232
248
|
|
|
233
249
|
```typescript
|
|
234
|
-
// 基本使用
|
|
235
250
|
generateRouter()
|
|
236
|
-
|
|
237
|
-
// 自定义 pages.json 路径
|
|
238
251
|
generateRouter({ pagesJsonPath: 'pages.json' })
|
|
239
|
-
|
|
240
|
-
// 输出 JavaScript 文件
|
|
241
252
|
generateRouter({ outputFormat: 'js', outputPath: 'src/router.config.js' })
|
|
242
|
-
|
|
243
|
-
// 使用帕斯卡命名策略
|
|
244
253
|
generateRouter({ nameStrategy: 'pascalCase' })
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
generateRouter({
|
|
248
|
-
nameStrategy: 'custom',
|
|
249
|
-
customNameGenerator: path => `route_${path.replace(/\//g, '_')}`
|
|
250
|
-
})
|
|
251
|
-
|
|
252
|
-
// 自定义元信息映射
|
|
253
|
-
generateRouter({
|
|
254
|
-
metaMapping: {
|
|
255
|
-
navigationBarTitleText: 'title',
|
|
256
|
-
requireAuth: 'requireAuth',
|
|
257
|
-
customField: 'custom'
|
|
258
|
-
}
|
|
259
|
-
})
|
|
254
|
+
generateRouter({ nameStrategy: 'custom', customNameGenerator: path => `route_${path.replace(/\//g, '_')}` })
|
|
255
|
+
generateRouter({ metaMapping: { navigationBarTitleText: 'title', requireAuth: 'requireAuth', customField: 'custom' } })
|
|
260
256
|
```
|
|
261
257
|
|
|
258
|
+
---
|
|
259
|
+
|
|
262
260
|
### generateVersion
|
|
263
261
|
|
|
264
262
|
在 Vite 构建过程中自动生成版本号。
|
|
@@ -297,34 +295,16 @@ generateRouter({
|
|
|
297
295
|
> 当 `format` 为 `'custom'` 时,必须提供 `customFormat`。当 `outputType` 为 `'define'` 或 `'both'` 时,同时注入 `{defineName}_INFO` 全局变量,包含版本号、构建时间、时间戳等完整信息。
|
|
298
296
|
|
|
299
297
|
```typescript
|
|
300
|
-
// 时间戳格式(默认)
|
|
301
298
|
generateVersion()
|
|
302
|
-
|
|
303
|
-
// 日期格式
|
|
304
299
|
generateVersion({ format: 'date' })
|
|
305
|
-
|
|
306
|
-
// 语义化版本格式
|
|
307
300
|
generateVersion({ format: 'semver', semverBase: '2.0.0', prefix: 'v' })
|
|
308
|
-
|
|
309
|
-
// 自定义格式
|
|
310
|
-
generateVersion({
|
|
311
|
-
format: 'custom',
|
|
312
|
-
customFormat: '{YYYY}.{MM}.{DD}-{hash}',
|
|
313
|
-
hashLength: 6
|
|
314
|
-
})
|
|
315
|
-
|
|
316
|
-
// 注入到代码中
|
|
301
|
+
generateVersion({ format: 'custom', customFormat: '{YYYY}.{MM}.{DD}-{hash}', hashLength: 6 })
|
|
317
302
|
generateVersion({ outputType: 'define', defineName: '__VERSION__' })
|
|
318
|
-
|
|
319
|
-
// 同时输出文件和注入代码
|
|
320
|
-
generateVersion({
|
|
321
|
-
outputType: 'both',
|
|
322
|
-
outputFile: 'build-info.json',
|
|
323
|
-
defineName: '__BUILD_VERSION__',
|
|
324
|
-
extra: { environment: 'production' }
|
|
325
|
-
})
|
|
303
|
+
generateVersion({ outputType: 'both', outputFile: 'build-info.json', defineName: '__BUILD_VERSION__', extra: { environment: 'production' } })
|
|
326
304
|
```
|
|
327
305
|
|
|
306
|
+
---
|
|
307
|
+
|
|
328
308
|
### versionUpdateChecker
|
|
329
309
|
|
|
330
310
|
在运行时定期检查版本号变更,发现新版本时提示用户刷新页面。通常与 `generateVersion` 插件配合使用。
|
|
@@ -357,628 +337,560 @@ generateVersion({
|
|
|
357
337
|
> `{{message}}`、`{{currentVersion}}`、`{{newVersion}}`、`{{refreshButton}}`、`{{dismissButton}}` 占位符。回调以函数体字符串形式提供,可用变量:`currentVersion`、`newVersion`。
|
|
358
338
|
|
|
359
339
|
```typescript
|
|
360
|
-
// 基本使用(配合 generateVersion)
|
|
361
340
|
generateVersion({ outputType: 'both' })
|
|
362
341
|
versionUpdateChecker()
|
|
363
|
-
|
|
364
|
-
// 仅从版本文件读取
|
|
365
342
|
versionUpdateChecker({ versionSource: 'file' })
|
|
366
|
-
|
|
367
|
-
// 自定义检查间隔和提示样式
|
|
368
|
-
versionUpdateChecker({
|
|
369
|
-
checkInterval: 60000,
|
|
370
|
-
promptStyle: 'banner'
|
|
371
|
-
})
|
|
372
|
-
|
|
373
|
-
// 底部轻提示
|
|
343
|
+
versionUpdateChecker({ checkInterval: 60000, promptStyle: 'banner' })
|
|
374
344
|
versionUpdateChecker({ promptStyle: 'toast' })
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
versionUpdateChecker({
|
|
378
|
-
promptMessage: '系统已更新,建议刷新体验新功能',
|
|
379
|
-
refreshButtonText: '更新',
|
|
380
|
-
dismissButtonText: '取消'
|
|
381
|
-
})
|
|
382
|
-
|
|
383
|
-
// 自定义回调
|
|
384
|
-
versionUpdateChecker({
|
|
385
|
-
onUpdateAvailable: 'console.log("新版本:", newVersion); return true;',
|
|
386
|
-
onRefresh: 'console.log("用户选择刷新");',
|
|
387
|
-
onDismiss: 'console.log("用户选择忽略");'
|
|
388
|
-
})
|
|
389
|
-
|
|
390
|
-
// 开发环境也启用(调试用)
|
|
345
|
+
versionUpdateChecker({ promptMessage: '系统已更新,建议刷新体验新功能', refreshButtonText: '更新', dismissButtonText: '取消' })
|
|
346
|
+
versionUpdateChecker({ onUpdateAvailable: 'console.log("新版本:", newVersion); return true;', onRefresh: 'console.log("用户选择刷新");', onDismiss: 'console.log("用户选择忽略");' })
|
|
391
347
|
versionUpdateChecker({ enableInDev: true })
|
|
392
348
|
```
|
|
393
349
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
在 Vite 构建过程中根据配置规则将 HTML 内容注入到目标文件中,支持多种注入位置、条件注入、模板变量替换和安全过滤。
|
|
350
|
+
---
|
|
397
351
|
|
|
398
|
-
|
|
352
|
+
### htmlInject
|
|
399
353
|
|
|
400
|
-
|
|
401
|
-
| ------------------ | -------------------------- |
|
|
402
|
-
| `head-start` | 注入到 `<head>` 标签开始后 |
|
|
403
|
-
| `head-end` | 注入到 `</head>` 标签前 |
|
|
404
|
-
| `body-start` | 注入到 `<body>` 标签开始后 |
|
|
405
|
-
| `body-end` | 注入到 `</body>` 标签前 |
|
|
406
|
-
| `before-selector` | 注入到选择器匹配内容前 |
|
|
407
|
-
| `after-selector` | 注入到选择器匹配内容后 |
|
|
408
|
-
| `replace-selector` | 替换选择器匹配的内容 |
|
|
354
|
+
在 HTML 文件中注入自定义内容,支持多种位置、选择器定位、条件注入、模板变量替换和安全过滤。
|
|
409
355
|
|
|
410
356
|
| 选项 | 类型 | 默认值 | 描述 |
|
|
411
357
|
| ------------ | ------------------------ | -------------- | -------------------------- |
|
|
412
358
|
| targetFile | `string` | `'index.html'` | 目标 HTML 文件路径或文件名 |
|
|
413
|
-
| rules | `InjectRule[]` | - |
|
|
359
|
+
| rules | `InjectRule[]` | - | 注入规则列表(必填) |
|
|
414
360
|
| security | `SecurityConfig` | - | 安全过滤配置 |
|
|
415
|
-
| templateVars | `Record<string, string>` |
|
|
416
|
-
| logInjection | `boolean` | `true` |
|
|
361
|
+
| templateVars | `Record<string, string>` | `{}` | 全局模板变量映射 |
|
|
362
|
+
| logInjection | `boolean` | `true` | 是否在控制台输出注入日志 |
|
|
417
363
|
|
|
418
364
|
**InjectRule**
|
|
419
365
|
|
|
420
|
-
| 属性 | 类型
|
|
421
|
-
| -------------------- |
|
|
422
|
-
| id | `string`
|
|
423
|
-
| content | `string`
|
|
424
|
-
| position | `
|
|
425
|
-
| selector | `string`
|
|
426
|
-
| selectorMatch | `'string'` \| `'regex'`
|
|
427
|
-
| priority | `number`
|
|
428
|
-
| condition | `InjectCondition`
|
|
429
|
-
| templateVars | `Record<string, string>`
|
|
430
|
-
| allowScriptInjection | `boolean`
|
|
366
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
367
|
+
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ---------- | --------------------------------------- |
|
|
368
|
+
| id | `string` | - | 规则唯一标识 |
|
|
369
|
+
| content | `string` | - | 注入内容 |
|
|
370
|
+
| position | `'head-start'` \| `'head-end'` \| `'body-start'` \| `'body-end'` \| `'before-selector'` \| `'after-selector'` \| `'replace-selector'` | - | 注入位置 |
|
|
371
|
+
| selector | `string` | - | 选择器字符串(selector 相关位置时必填) |
|
|
372
|
+
| selectorMatch | `'string'` \| `'regex'` | `'string'` | 选择器匹配模式 |
|
|
373
|
+
| priority | `number` | `100` | 规则优先级,数值越小越先执行 |
|
|
374
|
+
| condition | `InjectCondition` | - | 注入条件 |
|
|
375
|
+
| templateVars | `Record<string, string>` | - | 规则级模板变量(覆盖全局 templateVars) |
|
|
376
|
+
| allowScriptInjection | `boolean` | `false` | 是否允许注入脚本等危险内容 |
|
|
431
377
|
|
|
432
378
|
**InjectCondition**
|
|
433
379
|
|
|
434
|
-
| 属性 | 类型
|
|
435
|
-
| ------ |
|
|
436
|
-
| type | `'env'` \| `'file-contains'` \| `'custom'`
|
|
437
|
-
| value | `string` \| `(
|
|
438
|
-
| negate | `boolean`
|
|
380
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
381
|
+
| ------ | ------------------------------------------ | ------- | ------------------ |
|
|
382
|
+
| type | `'env'` \| `'file-contains'` \| `'custom'` | - | 条件类型 |
|
|
383
|
+
| value | `string` \| `(...args: any[]) => boolean` | - | 条件值 |
|
|
384
|
+
| negate | `boolean` | `false` | 是否对条件结果取反 |
|
|
439
385
|
|
|
440
386
|
**SecurityConfig**
|
|
441
387
|
|
|
442
|
-
| 属性 | 类型 | 默认值 | 描述
|
|
443
|
-
| ------------------------ | ---------- | ------ |
|
|
444
|
-
| blockDangerousTags | `boolean` | `true` |
|
|
445
|
-
| blockDangerousAttributes | `boolean` | `true` |
|
|
446
|
-
| allowedTags | `string[]` | - | 允许通过的标签白名单
|
|
447
|
-
| blockedTags | `string[]` | - | 自定义阻止标签列表
|
|
448
|
-
| blockedAttributes | `string[]` | - | 自定义阻止属性列表
|
|
388
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
389
|
+
| ------------------------ | ---------- | ------ | ------------------------------ |
|
|
390
|
+
| blockDangerousTags | `boolean` | `true` | 是否阻止危险标签(script 等) |
|
|
391
|
+
| blockDangerousAttributes | `boolean` | `true` | 是否阻止危险属性(onclick 等) |
|
|
392
|
+
| allowedTags | `string[]` | - | 允许通过的标签白名单 |
|
|
393
|
+
| blockedTags | `string[]` | - | 自定义阻止标签列表 |
|
|
394
|
+
| blockedAttributes | `string[]` | - | 自定义阻止属性列表 |
|
|
449
395
|
|
|
450
396
|
```typescript
|
|
451
|
-
// 基本使用
|
|
452
|
-
htmlInject({
|
|
453
|
-
rules: [{ id: 'meta-desc', content: '<meta name="description" content="My App">', position: 'head-end' }]
|
|
454
|
-
})
|
|
455
|
-
|
|
456
|
-
// 条件注入(仅生产环境)
|
|
457
397
|
htmlInject({
|
|
458
398
|
rules: [
|
|
459
|
-
{
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
allowScriptInjection: true
|
|
465
|
-
}
|
|
399
|
+
{ id: 'meta-description', content: '<meta name="description" content="My App">', position: 'head-end' },
|
|
400
|
+
{ id: 'analytics', content: '<script src="https://analytics.example.com/track.js"></script>', position: 'body-end', allowScriptInjection: true },
|
|
401
|
+
{ id: 'env-var', content: '<script>window.__ENV__ = "{{env}}"</script>', position: 'head-end', templateVars: { env: 'production' }, allowScriptInjection: true },
|
|
402
|
+
{ id: 'before-app', content: '<div>Before App</div>', position: 'before-selector', selector: '<div id="app">' },
|
|
403
|
+
{ id: 'prod-only', content: '<meta name="robots" content="noindex">', position: 'head-end', condition: { type: 'env', value: 'PRODUCTION' } }
|
|
466
404
|
]
|
|
467
405
|
})
|
|
468
|
-
|
|
469
|
-
// 模板变量替换
|
|
470
|
-
htmlInject({
|
|
471
|
-
templateVars: { appName: 'My App', version: '1.0.0' },
|
|
472
|
-
rules: [{ id: 'meta', content: '<meta name="description" content="{{appName}}">', position: 'head-end' }]
|
|
473
|
-
})
|
|
474
|
-
|
|
475
|
-
// 选择器注入
|
|
476
|
-
htmlInject({
|
|
477
|
-
rules: [{ id: 'replace-title', content: '<title>New Title</title>', position: 'replace-selector', selector: '<title>.*</title>', selectorMatch: 'regex' }]
|
|
478
|
-
})
|
|
479
|
-
|
|
480
|
-
// 安全配置
|
|
481
|
-
htmlInject({
|
|
482
|
-
security: { blockDangerousTags: true, allowedTags: ['iframe'] },
|
|
483
|
-
rules: [{ id: 'embed', content: '<iframe src="https://example.com"></iframe>', position: 'body-end' }]
|
|
484
|
-
})
|
|
485
406
|
```
|
|
486
407
|
|
|
487
|
-
|
|
408
|
+
---
|
|
488
409
|
|
|
489
|
-
|
|
410
|
+
### faviconManager
|
|
490
411
|
|
|
491
|
-
|
|
492
|
-
| ----------- | -------- | ------ | --------------------------- |
|
|
493
|
-
| base | `string` | `'/'` | 图标文件的基础路径 |
|
|
494
|
-
| url | `string` | - | 图标的完整 URL |
|
|
495
|
-
| link | `string` | - | 自定义完整的 link 标签 HTML |
|
|
496
|
-
| icons | `Icon[]` | - | 自定义图标数组 |
|
|
497
|
-
| copyOptions | `object` | - | 图标文件复制配置 |
|
|
412
|
+
管理网站图标链接注入到 HTML 文件,支持图标文件复制,支持字符串简写配置。
|
|
498
413
|
|
|
499
|
-
|
|
414
|
+
| 选项 | 类型 | 默认值 | 描述 |
|
|
415
|
+
| ----------- | ------------- | ------ | ----------------------------------------- |
|
|
416
|
+
| base | `string` | `'/'` | 图标文件的基础路径 |
|
|
417
|
+
| url | `string` | - | 图标完整 URL(优先于 base + favicon.ico) |
|
|
418
|
+
| link | `string` | - | 自定义完整 link 标签 HTML(最高优先级) |
|
|
419
|
+
| icons | `Icon[]` | - | 自定义图标数组,支持多种格式和尺寸 |
|
|
420
|
+
| copyOptions | `CopyOptions` | - | 图标文件复制配置 |
|
|
500
421
|
|
|
501
|
-
|
|
422
|
+
**Icon**
|
|
502
423
|
|
|
503
|
-
| 属性 | 类型 |
|
|
504
|
-
| ----- | -------- |
|
|
505
|
-
| rel | `string` |
|
|
506
|
-
| href | `string` |
|
|
507
|
-
| sizes | `string` |
|
|
508
|
-
| type | `string` |
|
|
424
|
+
| 属性 | 类型 | 描述 |
|
|
425
|
+
| ----- | -------- | -------------- |
|
|
426
|
+
| rel | `string` | 图标关系类型 |
|
|
427
|
+
| href | `string` | 图标 URL |
|
|
428
|
+
| sizes | `string` | 图标尺寸 |
|
|
429
|
+
| type | `string` | 图标 MIME 类型 |
|
|
509
430
|
|
|
510
|
-
|
|
431
|
+
**CopyOptions**
|
|
511
432
|
|
|
512
|
-
| 属性 | 类型 |
|
|
513
|
-
| --------- | --------- |
|
|
514
|
-
| sourceDir | `string` |
|
|
515
|
-
| targetDir | `string` |
|
|
516
|
-
| overwrite | `boolean` |
|
|
517
|
-
| recursive | `boolean` |
|
|
433
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
434
|
+
| --------- | --------- | ------ | ---------------------- |
|
|
435
|
+
| sourceDir | `string` | - | 图标源文件目录(必填) |
|
|
436
|
+
| targetDir | `string` | - | 图标目标目录(必填) |
|
|
437
|
+
| overwrite | `boolean` | `true` | 是否覆盖同名文件 |
|
|
438
|
+
| recursive | `boolean` | `true` | 是否递归复制 |
|
|
518
439
|
|
|
519
440
|
```typescript
|
|
520
|
-
// 使用默认配置
|
|
521
|
-
faviconManager()
|
|
522
|
-
|
|
523
|
-
// 字符串简写(设置 base 路径)
|
|
524
441
|
faviconManager('/assets')
|
|
525
|
-
|
|
526
|
-
// 自定义图标数组
|
|
442
|
+
faviconManager({ base: '/assets', url: '/assets/favicon.ico' })
|
|
527
443
|
faviconManager({
|
|
528
444
|
base: '/assets',
|
|
529
445
|
icons: [
|
|
530
446
|
{ rel: 'icon', href: '/favicon.svg', type: 'image/svg+xml' },
|
|
531
|
-
{ rel: 'icon', href: '/favicon-32x32.png', sizes: '32x32', type: 'image/png' }
|
|
532
|
-
{ rel: 'apple-touch-icon', href: '/apple-touch-icon.png', sizes: '180x180' }
|
|
447
|
+
{ rel: 'icon', href: '/favicon-32x32.png', sizes: '32x32', type: 'image/png' }
|
|
533
448
|
]
|
|
534
449
|
})
|
|
535
|
-
|
|
536
|
-
// 自定义完整 link 标签
|
|
537
|
-
faviconManager({
|
|
538
|
-
link: '<link rel="icon" href="/favicon.svg" type="image/svg+xml" />'
|
|
539
|
-
})
|
|
540
|
-
|
|
541
|
-
// 带文件复制
|
|
542
450
|
faviconManager({
|
|
543
451
|
base: '/assets',
|
|
544
|
-
copyOptions: {
|
|
545
|
-
sourceDir: 'src/assets/icons',
|
|
546
|
-
targetDir: 'dist/assets/icons'
|
|
547
|
-
}
|
|
452
|
+
copyOptions: { sourceDir: 'src/assets/icons', targetDir: 'dist/assets/icons' }
|
|
548
453
|
})
|
|
549
454
|
```
|
|
550
455
|
|
|
456
|
+
---
|
|
457
|
+
|
|
551
458
|
### loadingManager
|
|
552
459
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
|
561
|
-
|
|
|
562
|
-
|
|
|
563
|
-
|
|
|
564
|
-
|
|
|
565
|
-
|
|
|
566
|
-
|
|
|
567
|
-
|
|
|
568
|
-
|
|
|
569
|
-
|
|
|
570
|
-
|
|
|
571
|
-
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
460
|
+
全局 Loading 状态管理,支持请求拦截、防抖、过渡动画和白屏 Loading。
|
|
461
|
+
|
|
462
|
+
| 选项 | 类型 | 默认值 | 描述 |
|
|
463
|
+
| -------------- | ------------------ | ----------------------- | ------------------------------------------------ |
|
|
464
|
+
| position | `LoadingPosition` | `'center'` | Loading 显示位置 |
|
|
465
|
+
| defaultText | `string` | `'加载中...'` | 默认显示文本 |
|
|
466
|
+
| spinnerType | `SpinnerType` | `'spinner'` | 旋转图标类型 |
|
|
467
|
+
| style | `LoadingStyle` | - | 自定义样式配置 |
|
|
468
|
+
| transition | `TransitionConfig` | - | 过渡动画配置 |
|
|
469
|
+
| minDisplayTime | `MinDisplayTime` | - | 最小显示时间配置 |
|
|
470
|
+
| delayShow | `DelayShow` | - | 延迟显示配置 |
|
|
471
|
+
| debounceHide | `DebounceHide` | - | 防抖隐藏配置 |
|
|
472
|
+
| autoBind | `AutoBindMode` | `'none'` | 自动绑定请求拦截模式 |
|
|
473
|
+
| requestFilter | `RequestFilter` | - | 请求过滤配置 |
|
|
474
|
+
| globalName | `string` | `'__LOADING_MANAGER__'` | 注入的全局变量名 |
|
|
475
|
+
| customTemplate | `string` | - | 自定义 Loading HTML 模板 |
|
|
476
|
+
| defaultVisible | `boolean` | `false` | Loading DOM 初始可见状态(白屏 Loading) |
|
|
477
|
+
| autoHideOn | `AutoHideOn` | `'DOMContentLoaded'` | 自动隐藏时机(仅 defaultVisible 为 true 时生效) |
|
|
478
|
+
| callbacks | `LoadingCallbacks` | - | 生命周期回调 |
|
|
479
|
+
|
|
480
|
+
**LoadingPosition**:`'center'` | `'top'` | `'bottom'`
|
|
481
|
+
|
|
482
|
+
**SpinnerType**:`'spinner'` | `'dots'` | `'pulse'` | `'bar'`
|
|
483
|
+
|
|
484
|
+
**AutoBindMode**:`'fetch'` | `'xhr'` | `'all'` | `'none'`
|
|
485
|
+
|
|
486
|
+
**AutoHideOn**:`'DOMContentLoaded'` | `'load'` | `'manual'`
|
|
577
487
|
|
|
578
488
|
**LoadingStyle**
|
|
579
489
|
|
|
580
490
|
| 属性 | 类型 | 默认值 | 描述 |
|
|
581
491
|
| ------------------ | --------- | ------------------------- | ---------------------- |
|
|
582
492
|
| overlayColor | `string` | `'rgba(255,255,255,0.7)'` | 遮罩层背景色 |
|
|
583
|
-
| spinnerColor | `string` | `'#4361ee'` | 图标颜色
|
|
584
|
-
| spinnerSize | `string` | `'40px'` | 图标大小
|
|
493
|
+
| spinnerColor | `string` | `'#4361ee'` | Loading 图标颜色 |
|
|
494
|
+
| spinnerSize | `string` | `'40px'` | Loading 图标大小 |
|
|
585
495
|
| textColor | `string` | `'#333'` | 文本颜色 |
|
|
586
496
|
| textSize | `string` | `'14px'` | 文本大小 |
|
|
587
497
|
| customClass | `string` | - | 自定义 CSS 类名 |
|
|
588
|
-
| customStyle | `string` | - |
|
|
589
|
-
| zIndex | `number` | `9999` | z-index
|
|
498
|
+
| customStyle | `string` | - | 自定义内联样式字符串 |
|
|
499
|
+
| zIndex | `number` | `9999` | 遮罩层 z-index |
|
|
590
500
|
| pointerEvents | `boolean` | `true` | 是否启用遮罩层指针事件 |
|
|
591
|
-
| backdropBlur | `boolean` | `false` |
|
|
501
|
+
| backdropBlur | `boolean` | `false` | 是否启用背景模糊效果 |
|
|
592
502
|
| backdropBlurAmount | `number` | `4` | 背景模糊程度(px) |
|
|
593
503
|
|
|
594
504
|
**TransitionConfig**
|
|
595
505
|
|
|
596
|
-
| 属性 | 类型 | 默认值 | 描述
|
|
597
|
-
| -------- | --------- | ------------ |
|
|
598
|
-
| enabled | `boolean` | `true` |
|
|
599
|
-
| duration | `number` | `200` |
|
|
600
|
-
| easing | `string` | `'ease-out'` |
|
|
506
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
507
|
+
| -------- | --------- | ------------ | ---------------------- |
|
|
508
|
+
| enabled | `boolean` | `true` | 是否启用过渡动画 |
|
|
509
|
+
| duration | `number` | `200` | 过渡动画持续时间(ms) |
|
|
510
|
+
| easing | `string` | `'ease-out'` | CSS 过渡缓动函数 |
|
|
601
511
|
|
|
602
512
|
**MinDisplayTime**
|
|
603
513
|
|
|
604
|
-
| 属性 | 类型 | 默认值 | 描述
|
|
605
|
-
| -------- | --------- | ------ |
|
|
606
|
-
| enabled | `boolean` | `true` |
|
|
607
|
-
| duration | `number` | `300` |
|
|
514
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
515
|
+
| -------- | --------- | ------ | -------------------- |
|
|
516
|
+
| enabled | `boolean` | `true` | 是否启用最小显示时间 |
|
|
517
|
+
| duration | `number` | `300` | 最小显示时间(ms) |
|
|
608
518
|
|
|
609
519
|
**DelayShow**
|
|
610
520
|
|
|
611
|
-
| 属性 | 类型 | 默认值 | 描述
|
|
612
|
-
| -------- | --------- | ------ |
|
|
613
|
-
| enabled | `boolean` | `true` |
|
|
614
|
-
| duration | `number` | `200` |
|
|
521
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
522
|
+
| -------- | --------- | ------ | ------------------------------------------ |
|
|
523
|
+
| enabled | `boolean` | `true` | 是否启用延迟显示 |
|
|
524
|
+
| duration | `number` | `200` | 延迟时间(ms),请求在此时间内完成则不显示 |
|
|
615
525
|
|
|
616
526
|
**DebounceHide**
|
|
617
527
|
|
|
618
|
-
| 属性 | 类型 | 默认值 | 描述
|
|
619
|
-
| -------- | --------- | ------- |
|
|
620
|
-
| enabled | `boolean` | `false` |
|
|
621
|
-
| duration | `number` | `100` |
|
|
528
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
529
|
+
| -------- | --------- | ------- | ------------------ |
|
|
530
|
+
| enabled | `boolean` | `false` | 是否启用防抖隐藏 |
|
|
531
|
+
| duration | `number` | `100` | 防抖等待时间(ms) |
|
|
622
532
|
|
|
623
533
|
**RequestFilter**
|
|
624
534
|
|
|
625
|
-
| 属性 | 类型 | 描述
|
|
626
|
-
| ------------------ | ---------- |
|
|
627
|
-
| excludeUrls | `RegExp[]` |
|
|
628
|
-
| includeUrls | `RegExp[]` |
|
|
629
|
-
| excludeMethods | `string[]` |
|
|
630
|
-
| excludeUrlPrefixes | `string[]` |
|
|
535
|
+
| 属性 | 类型 | 描述 |
|
|
536
|
+
| ------------------ | ---------- | ----------------------------- |
|
|
537
|
+
| excludeUrls | `RegExp[]` | 需要排除的 URL 正则表达式数组 |
|
|
538
|
+
| includeUrls | `RegExp[]` | 需要包含的 URL 正则表达式数组 |
|
|
539
|
+
| excludeMethods | `string[]` | 需要排除的 HTTP 方法数组 |
|
|
540
|
+
| excludeUrlPrefixes | `string[]` | 需要排除的 URL 字符串前缀数组 |
|
|
631
541
|
|
|
632
542
|
**LoadingCallbacks**
|
|
633
543
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
|
637
|
-
|
|
|
638
|
-
|
|
|
639
|
-
|
|
|
640
|
-
|
|
|
641
|
-
| onHide | `string` | 隐藏后回调 |
|
|
642
|
-
| onDestroy | `string` | 销毁时回调 |
|
|
643
|
-
|
|
644
|
-
**LoadingManager API**
|
|
645
|
-
|
|
646
|
-
通过 `window.__LOADING_MANAGER__` 访问:
|
|
647
|
-
|
|
648
|
-
| 方法 | 说明 |
|
|
649
|
-
| -------------------------- | ------------------------------------------ |
|
|
650
|
-
| `show(text?)` | 显示 Loading,可传入文本 |
|
|
651
|
-
| `hide()` | 隐藏 Loading(受最小显示时间和防抖约束) |
|
|
652
|
-
| `forceHide()` | 强制隐藏,忽略最小显示时间和防抖 |
|
|
653
|
-
| `toggle(text?)` | 切换 Loading 显示/隐藏状态 |
|
|
654
|
-
| `updateText(text)` | 更新文本内容 |
|
|
655
|
-
| `isVisible()` | 获取当前是否显示 |
|
|
656
|
-
| `isPointerEventsEnabled()` | 获取当前是否启用了指针事件 |
|
|
657
|
-
| `enablePointerEvents()` | 启用遮罩层指针事件,拦截所有点击和滚动操作 |
|
|
658
|
-
| `disablePointerEvents()` | 禁用遮罩层指针事件,允许交互穿透 |
|
|
659
|
-
| `togglePointerEvents()` | 切换遮罩层指针事件状态 |
|
|
660
|
-
| `getPendingCount()` | 获取当前挂起的请求数量 |
|
|
661
|
-
| `destroy()` | 销毁实例,清理 DOM 并恢复原始拦截器 |
|
|
662
|
-
|
|
663
|
-
```typescript
|
|
664
|
-
// 白屏 Loading:页面加载即显示,DOM 就绪后自动隐藏
|
|
665
|
-
loadingManager({ defaultVisible: true, autoHideOn: 'DOMContentLoaded' })
|
|
666
|
-
|
|
667
|
-
// 白屏 Loading:所有资源加载完成后隐藏
|
|
668
|
-
loadingManager({ defaultVisible: true, autoHideOn: 'load' })
|
|
669
|
-
|
|
670
|
-
// Vue/React SPA:白屏即显示,框架渲染完成后手动隐藏
|
|
671
|
-
loadingManager({ defaultVisible: true, autoHideOn: 'manual' })
|
|
672
|
-
// 在应用入口处:window.__LOADING_MANAGER__.hide()
|
|
673
|
-
|
|
674
|
-
// 自动拦截所有请求
|
|
675
|
-
loadingManager({ autoBind: 'all' })
|
|
544
|
+
| 属性 | 类型 | 描述 |
|
|
545
|
+
| ------------ | -------- | --------------------------------------- |
|
|
546
|
+
| onBeforeShow | `string` | 显示前回调(`return false` 可阻止显示) |
|
|
547
|
+
| onShow | `string` | 显示后回调 |
|
|
548
|
+
| onBeforeHide | `string` | 隐藏前回调(`return false` 可阻止隐藏) |
|
|
549
|
+
| onHide | `string` | 隐藏后回调 |
|
|
550
|
+
| onDestroy | `string` | 销毁时回调 |
|
|
676
551
|
|
|
677
|
-
|
|
678
|
-
loadingManager({
|
|
679
|
-
style: { overlayColor: 'rgba(0,0,0,0.5)', spinnerColor: '#fff', backdropBlur: true },
|
|
680
|
-
autoBind: 'fetch',
|
|
681
|
-
requestFilter: { excludeUrls: [/\/api\/health/], excludeUrlPrefixes: ['http://localhost'] }
|
|
682
|
-
})
|
|
683
|
-
|
|
684
|
-
// 防抖隐藏(避免快速闪烁)
|
|
685
|
-
loadingManager({ debounceHide: { enabled: true, duration: 100 } })
|
|
552
|
+
> 回调以函数体字符串形式提供,因为需要注入到客户端代码中。`customTemplate` 中必须包含具有 `data-loading-text` 属性的元素用于文本显示。
|
|
686
553
|
|
|
687
|
-
|
|
688
|
-
loadingManager({
|
|
689
|
-
callbacks: {
|
|
690
|
-
onBeforeShow: 'if (shouldSkip) return false;',
|
|
691
|
-
onShow: 'console.log("loading shown")',
|
|
692
|
-
onBeforeHide: 'if (shouldKeepVisible) return false;',
|
|
693
|
-
onHide: 'console.log("loading hidden")'
|
|
694
|
-
}
|
|
695
|
-
})
|
|
554
|
+
**运行时 API:**
|
|
696
555
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
window.__LOADING_MANAGER__.show('正在保存...')
|
|
556
|
+
```typescript
|
|
557
|
+
window.__LOADING_MANAGER__.show('加载中...')
|
|
700
558
|
window.__LOADING_MANAGER__.hide()
|
|
701
|
-
window.__LOADING_MANAGER__.
|
|
559
|
+
window.__LOADING_MANAGER__.forceHide()
|
|
560
|
+
window.__LOADING_MANAGER__.toggle('正在加载...')
|
|
561
|
+
window.__LOADING_MANAGER__.updateText('正在处理...')
|
|
562
|
+
window.__LOADING_MANAGER__.isVisible()
|
|
563
|
+
window.__LOADING_MANAGER__.getPendingCount()
|
|
564
|
+
window.__LOADING_MANAGER__.enablePointerEvents()
|
|
702
565
|
window.__LOADING_MANAGER__.disablePointerEvents()
|
|
566
|
+
window.__LOADING_MANAGER__.destroy()
|
|
703
567
|
```
|
|
704
568
|
|
|
705
|
-
## 通用工具函数
|
|
706
|
-
|
|
707
|
-
通过 `@meng-xi/vite-plugin/common` 导出,可在自定义插件中复用:
|
|
708
|
-
|
|
709
569
|
```typescript
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
570
|
+
loadingManager()
|
|
571
|
+
loadingManager({ defaultVisible: true, autoHideOn: 'DOMContentLoaded' })
|
|
572
|
+
loadingManager({ position: 'top', defaultText: '请稍候...', spinnerType: 'dots' })
|
|
573
|
+
loadingManager({ autoBind: 'fetch', requestFilter: { excludeUrls: [/\/api\/health/] } })
|
|
574
|
+
loadingManager({
|
|
575
|
+
style: { overlayColor: 'rgba(0,0,0,0.5)', spinnerColor: '#ff6b6b', backdropBlur: true, backdropBlurAmount: 6 }
|
|
576
|
+
})
|
|
577
|
+
loadingManager({ transition: { enabled: true, duration: 300, easing: 'cubic-bezier(0.4,0,0.2,1)' } })
|
|
578
|
+
loadingManager({ debounceHide: { enabled: true, duration: 100 } })
|
|
579
|
+
loadingManager({ callbacks: { onShow: 'console.log("shown")', onBeforeShow: 'return true' } })
|
|
580
|
+
loadingManager({ customTemplate: '<div class="my-loader"><span data-loading-text></span></div>' })
|
|
581
|
+
loadingManager({ defaultVisible: true, autoHideOn: 'manual' })
|
|
715
582
|
```
|
|
716
583
|
|
|
717
|
-
|
|
718
|
-
| ------------------------------- | --------------------------------------------------------------- | ------------------- |
|
|
719
|
-
| `deepMerge()` | 深度合并对象(undefined 不覆盖,数组直接覆盖) | `common/object` |
|
|
720
|
-
| `formatDate()` | 格式化日期,支持 `{YYYY}`, `{MM}`, `{DD}` 等占位符 | `common/format` |
|
|
721
|
-
| `parseTemplate()` | 解析模板字符串,替换占位符 | `common/format` |
|
|
722
|
-
| `toCamelCase()` | 转换为驼峰命名(camelCase) | `common/format` |
|
|
723
|
-
| `toPascalCase()` | 转换为帕斯卡命名(PascalCase) | `common/format` |
|
|
724
|
-
| `stripJsonComments()` | 移除 JSON 字符串中的注释 | `common/format` |
|
|
725
|
-
| `generateRandomHash()` | 生成随机哈希字符串(1-64 位) | `common/format` |
|
|
726
|
-
| `escapeHtmlAttr()` | 转义 HTML 属性值中的特殊字符,防止 XSS 注入 | `common/format` |
|
|
727
|
-
| `readFileContent()` | 异步读取文件内容 | `common/fs` |
|
|
728
|
-
| `writeFileContent()` | 异步写入文件内容 | `common/fs` |
|
|
729
|
-
| `fileExists()` | 异步检查文件是否存在 | `common/fs` |
|
|
730
|
-
| `copySourceToTarget()` | 复制文件或目录,支持增量复制和并发控制 | `common/fs` |
|
|
731
|
-
| `injectBeforeTag()` | 在 HTML 指定闭合标签前注入代码 | `common/html` |
|
|
732
|
-
| `injectHtmlByPriority()` | 按优先级向 HTML 中注入代码(`</head>` → `</body>` → `</html>`) | `common/html` |
|
|
733
|
-
| `injectBeforeTagWithFallback()` | 带回退策略的 HTML 注入(`</body>` → `</html>` → 末尾) | `common/html` |
|
|
734
|
-
| `injectHeadAndBody()` | 双区域 HTML 注入(head + body) | `common/html` |
|
|
735
|
-
| `makeCallback()` | 将回调函数体包装为安全的函数表达式(含 try-catch) | `common/script` |
|
|
736
|
-
| `containsScriptTag()` | 检测字符串是否包含 `<script>` 标签 | `common/script` |
|
|
737
|
-
| `validateIdentifierName()` | 验证字符串是否为合法的 JavaScript 标识符,防止原型污染 | `common/script` |
|
|
738
|
-
| `validateGlobalName()` | 验证全局变量名的合法性 | `common/validation` |
|
|
739
|
-
| `validateNoScriptInTemplate()` | 验证模板字符串不包含 script 标签(XSS 防护) | `common/validation` |
|
|
740
|
-
| `validateCallbackFields()` | 验证回调字段不包含 script 标签 | `common/validation` |
|
|
741
|
-
| `validateNonNegativeNumber()` | 验证数值为非负数 | `common/validation` |
|
|
742
|
-
| `validateNestedDuration()` | 验证嵌套配置项的 duration 合法性 | `common/validation` |
|
|
743
|
-
| `validateEnumValue()` | 验证字符串值是否在允许的枚举列表中 | `common/validation` |
|
|
584
|
+
---
|
|
744
585
|
|
|
745
586
|
## 插件开发框架
|
|
746
587
|
|
|
747
|
-
|
|
588
|
+
本包不仅提供内置插件,还导出完整的插件开发框架,帮助快速构建符合规范的自定义 Vite 插件。
|
|
748
589
|
|
|
749
|
-
|
|
590
|
+
### BasePlugin
|
|
750
591
|
|
|
751
|
-
|
|
592
|
+
所有内置插件的基类,提供配置管理、日志记录、错误处理和生命周期管理等核心能力。
|
|
752
593
|
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
| 配置解析 | `onConfigResolved` | Vite 配置解析完成时调用 |
|
|
757
|
-
| 钩子注册 | `addPluginHooks` | 注册 Vite 插件钩子 |
|
|
758
|
-
| 销毁 | `destroy` | `closeBundle` 时自动调用,用于清理资源 |
|
|
594
|
+
```typescript
|
|
595
|
+
import { BasePlugin, createPluginFactory } from '@meng-xi/vite-plugin'
|
|
596
|
+
import type { Plugin } from 'vite'
|
|
759
597
|
|
|
760
|
-
|
|
598
|
+
interface MyPluginOptions {
|
|
599
|
+
prefix?: string
|
|
600
|
+
}
|
|
761
601
|
|
|
762
|
-
|
|
602
|
+
class MyPlugin extends BasePlugin<MyPluginOptions> {
|
|
603
|
+
protected getPluginName() {
|
|
604
|
+
return 'my-plugin'
|
|
605
|
+
}
|
|
763
606
|
|
|
764
|
-
|
|
765
|
-
|
|
607
|
+
protected getDefaultOptions() {
|
|
608
|
+
return { prefix: '[app]' }
|
|
609
|
+
}
|
|
766
610
|
|
|
767
|
-
|
|
611
|
+
protected validateOptions() {
|
|
612
|
+
this.validator.field('prefix').string().notEmpty().validate()
|
|
613
|
+
}
|
|
768
614
|
|
|
769
|
-
|
|
615
|
+
protected addPluginHooks(plugin: Plugin) {
|
|
616
|
+
plugin.writeBundle = {
|
|
617
|
+
order: 'post',
|
|
618
|
+
handler: async () => {
|
|
619
|
+
await this.safeExecute(async () => {
|
|
620
|
+
this.logger.info('插件执行中...')
|
|
621
|
+
}, '执行自定义逻辑')
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
770
626
|
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
| `getPluginName()` | 返回插件名称 |
|
|
774
|
-
| `addPluginHooks(plugin)` | 添加 Vite 插件钩子 |
|
|
627
|
+
export const myPlugin = createPluginFactory(MyPlugin)
|
|
628
|
+
```
|
|
775
629
|
|
|
776
|
-
|
|
630
|
+
**BasePlugin 核心方法:**
|
|
631
|
+
|
|
632
|
+
| 方法 | 描述 |
|
|
633
|
+
| ------------------- | ------------------------------------------ |
|
|
634
|
+
| `getDefaultOptions` | 返回插件默认配置,子类可重写 |
|
|
635
|
+
| `validateOptions` | 校验用户配置,子类可重写 |
|
|
636
|
+
| `getPluginName` | 返回插件名称(抽象方法,必须实现) |
|
|
637
|
+
| `getEnforce` | 返回插件执行时机(pre / post / undefined) |
|
|
638
|
+
| `addPluginHooks` | 注册 Vite 钩子(抽象方法,必须实现) |
|
|
639
|
+
| `onConfigResolved` | 配置解析完成回调 |
|
|
640
|
+
| `destroy` | 插件销毁回调 |
|
|
641
|
+
| `safeExecute` | 安全执行异步函数,自动错误处理 |
|
|
642
|
+
| `safeExecuteSync` | 安全执行同步函数,自动错误处理 |
|
|
643
|
+
| `handleError` | 根据 errorStrategy 处理错误 |
|
|
644
|
+
| `toPlugin` | 转换为 Vite 插件对象 |
|
|
645
|
+
|
|
646
|
+
**BasePluginOptions 基础配置:**
|
|
647
|
+
|
|
648
|
+
| 选项 | 类型 | 默认值 | 描述 |
|
|
649
|
+
| ------------- | ---------------------------------- | --------- | ------------ |
|
|
650
|
+
| enabled | `boolean` | `true` | 是否启用插件 |
|
|
651
|
+
| verbose | `boolean` | `true` | 是否启用日志 |
|
|
652
|
+
| errorStrategy | `'throw'` \| `'log'` \| `'ignore'` | `'throw'` | 错误处理策略 |
|
|
777
653
|
|
|
778
|
-
|
|
779
|
-
| -------------------------- | ----------- | ---------------------------------- |
|
|
780
|
-
| `getDefaultOptions()` | 返回 `{}` | 提供插件默认配置 |
|
|
781
|
-
| `validateOptions()` | 无验证 | 验证配置参数 |
|
|
782
|
-
| `getEnforce()` | `undefined` | 插件执行时机(`'pre'` / `'post'`) |
|
|
783
|
-
| `onConfigResolved(config)` | 存储配置 | 配置解析完成回调 |
|
|
784
|
-
| `destroy()` | 注销日志 | 插件销毁时的清理逻辑 |
|
|
654
|
+
### createPluginFactory
|
|
785
655
|
|
|
786
|
-
|
|
656
|
+
创建插件工厂函数,将 BasePlugin 子类转换为可直接使用的 Vite 插件函数。
|
|
787
657
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
| `options` | `Required<T>` | 合并后的完整配置 |
|
|
791
|
-
| `logger` | `PluginLogger` | 插件日志记录器 |
|
|
792
|
-
| `validator` | `Validator<T>` | 配置验证器 |
|
|
793
|
-
| `viteConfig` | `ResolvedConfig \| null` | Vite 解析后的配置 |
|
|
658
|
+
```typescript
|
|
659
|
+
import { createPluginFactory } from '@meng-xi/vite-plugin'
|
|
794
660
|
|
|
795
|
-
|
|
661
|
+
const myPlugin = createPluginFactory(MyPlugin)
|
|
796
662
|
|
|
797
|
-
|
|
663
|
+
// 支持选项标准化器(如字符串简写配置)
|
|
664
|
+
const myPluginWithNormalizer = createPluginFactory(MyPlugin, opt => (typeof opt === 'string' ? { prefix: opt } : opt))
|
|
665
|
+
```
|
|
798
666
|
|
|
799
|
-
|
|
800
|
-
- `'log'` - 记录错误但不抛出,继续执行
|
|
801
|
-
- `'ignore'` - 记录错误但不抛出,继续执行
|
|
667
|
+
### Logger
|
|
802
668
|
|
|
803
|
-
|
|
669
|
+
全局单例日志管理器,为每个插件提供独立的日志代理。
|
|
804
670
|
|
|
805
671
|
```typescript
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
return someSyncOperation()
|
|
814
|
-
}, '执行同步操作')
|
|
672
|
+
import { Logger } from '@meng-xi/vite-plugin/logger'
|
|
673
|
+
|
|
674
|
+
const logger = Logger.create({ name: 'my-plugin', enabled: true })
|
|
675
|
+
logger.info('信息日志')
|
|
676
|
+
logger.success('成功日志')
|
|
677
|
+
logger.warn('警告日志')
|
|
678
|
+
logger.error('错误日志')
|
|
815
679
|
```
|
|
816
680
|
|
|
817
|
-
###
|
|
681
|
+
### Validator
|
|
818
682
|
|
|
819
|
-
|
|
683
|
+
链式配置验证器,用于校验插件配置参数。
|
|
820
684
|
|
|
821
685
|
```typescript
|
|
822
|
-
|
|
823
|
-
const myPlugin = createPluginFactory(MyPlugin)
|
|
686
|
+
import { Validator } from '@meng-xi/vite-plugin/common/validation'
|
|
824
687
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
// 使用时支持简写
|
|
829
|
-
myPlugin('./custom-path')
|
|
688
|
+
const validator = new Validator(myOptions)
|
|
689
|
+
validator.field('port').number().minValue(1).maxValue(65535).field('host').string().notEmpty().field('mode').enum(['development', 'production']).validate()
|
|
830
690
|
```
|
|
831
691
|
|
|
832
|
-
|
|
692
|
+
---
|
|
693
|
+
|
|
694
|
+
## Common 工具模块
|
|
833
695
|
|
|
834
|
-
|
|
696
|
+
内置通用工具函数库,按功能模块组织,支持子路径按需导入。
|
|
697
|
+
|
|
698
|
+
### 导入方式
|
|
835
699
|
|
|
836
700
|
```typescript
|
|
837
|
-
|
|
701
|
+
// 导入所有工具
|
|
702
|
+
import { formatFileSize, scanDirectory } from '@meng-xi/vite-plugin/common'
|
|
838
703
|
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
.field('targetDir')
|
|
845
|
-
.required()
|
|
846
|
-
.string()
|
|
847
|
-
.field('overwrite')
|
|
848
|
-
.boolean()
|
|
849
|
-
.default(true)
|
|
850
|
-
.field('port')
|
|
851
|
-
.number()
|
|
852
|
-
.field('list')
|
|
853
|
-
.array()
|
|
854
|
-
.field('config')
|
|
855
|
-
.object()
|
|
856
|
-
.field('name')
|
|
857
|
-
.custom(val => val.length > 0, 'name 不能为空')
|
|
858
|
-
.validate()
|
|
704
|
+
// 按模块导入
|
|
705
|
+
import { formatFileSize } from '@meng-xi/vite-plugin/common/format'
|
|
706
|
+
import { scanDirectory, writeJsonReport } from '@meng-xi/vite-plugin/common/fs'
|
|
707
|
+
import { calculateGzipSize } from '@meng-xi/vite-plugin/common/compress'
|
|
708
|
+
import { isNodeModule } from '@meng-xi/vite-plugin/common/path'
|
|
859
709
|
```
|
|
860
710
|
|
|
861
|
-
|
|
862
|
-
| ------------ | -------------------------------------------------- |
|
|
863
|
-
| `field()` | 指定要验证的字段 |
|
|
864
|
-
| `required()` | 标记字段为必填 |
|
|
865
|
-
| `string()` | 验证字段值是否为字符串类型 |
|
|
866
|
-
| `boolean()` | 验证字段值是否为布尔类型 |
|
|
867
|
-
| `number()` | 验证字段值是否为数字类型 |
|
|
868
|
-
| `array()` | 验证字段值是否为数组类型 |
|
|
869
|
-
| `object()` | 验证字段值是否为对象类型 |
|
|
870
|
-
| `enum()` | 验证字段值是否在允许的枚举列表中 |
|
|
871
|
-
| `minValue()` | 验证数字字段值是否不小于指定最小值 |
|
|
872
|
-
| `maxValue()` | 验证数字字段值是否不大于指定最大值 |
|
|
873
|
-
| `default()` | 为字段设置默认值(仅当值为 undefined/null 时生效) |
|
|
874
|
-
| `custom()` | 使用自定义函数验证字段值 |
|
|
875
|
-
| `validate()` | 执行验证,失败时抛出错误 |
|
|
711
|
+
### 模块列表
|
|
876
712
|
|
|
877
|
-
|
|
713
|
+
| 子路径 | 描述 |
|
|
714
|
+
| ---------------------------------------- | ------------- |
|
|
715
|
+
| `@meng-xi/vite-plugin/common/compress` | 压缩算法工具 |
|
|
716
|
+
| `@meng-xi/vite-plugin/common/format` | 格式化工具 |
|
|
717
|
+
| `@meng-xi/vite-plugin/common/fs` | 文件系统工具 |
|
|
718
|
+
| `@meng-xi/vite-plugin/common/html` | HTML 注入工具 |
|
|
719
|
+
| `@meng-xi/vite-plugin/common/object` | 对象操作工具 |
|
|
720
|
+
| `@meng-xi/vite-plugin/common/path` | 路径处理工具 |
|
|
721
|
+
| `@meng-xi/vite-plugin/common/script` | 脚本生成工具 |
|
|
722
|
+
| `@meng-xi/vite-plugin/common/validation` | 参数验证工具 |
|
|
723
|
+
|
|
724
|
+
### compress — 压缩算法
|
|
878
725
|
|
|
879
|
-
|
|
726
|
+
| 函数 | 描述 |
|
|
727
|
+
| ------------------- | -------------------------------------- |
|
|
728
|
+
| `calculateGzipSize` | 计算给定数据的 gzip 压缩后大小(字节) |
|
|
880
729
|
|
|
881
730
|
```typescript
|
|
882
|
-
import {
|
|
731
|
+
import { calculateGzipSize } from '@meng-xi/vite-plugin/common/compress'
|
|
883
732
|
|
|
884
|
-
|
|
885
|
-
|
|
733
|
+
const size = await calculateGzipSize(Buffer.from('hello world'))
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
### format — 格式化
|
|
737
|
+
|
|
738
|
+
| 函数 | 描述 |
|
|
739
|
+
| --------------------- | ---------------------------------------- |
|
|
740
|
+
| `formatFileSize` | 将字节数格式化为人类可读的文件大小字符串 |
|
|
741
|
+
| `getExtension` | 获取文件扩展名(小写) |
|
|
742
|
+
| `formatDate` | 格式化日期 |
|
|
743
|
+
| `parseTemplate` | 解析模板字符串,替换占位符 |
|
|
744
|
+
| `toCamelCase` | 字符串转驼峰命名 |
|
|
745
|
+
| `toPascalCase` | 字符串转帕斯卡命名 |
|
|
746
|
+
| `padNumber` | 数字补零格式化 |
|
|
747
|
+
| `generateRandomHash` | 生成随机哈希字符串 |
|
|
748
|
+
| `getDateFormatParams` | 获取日期格式化参数 |
|
|
749
|
+
| `stripJsonComments` | 移除 JSON 字符串中的注释 |
|
|
750
|
+
| `escapeHtmlAttr` | 转义 HTML 属性值中的特殊字符 |
|
|
886
751
|
|
|
887
|
-
|
|
888
|
-
|
|
752
|
+
```typescript
|
|
753
|
+
import { formatFileSize, formatDate, toCamelCase } from '@meng-xi/vite-plugin/common/format'
|
|
889
754
|
|
|
890
|
-
//
|
|
891
|
-
|
|
755
|
+
formatFileSize(2461726) // '2.35MB'
|
|
756
|
+
formatDate(new Date(), '{YYYY}-{MM}-{DD}') // '2026-05-31'
|
|
757
|
+
toCamelCase('pages/user/profile') // 'pagesUserProfile'
|
|
892
758
|
```
|
|
893
759
|
|
|
894
|
-
|
|
760
|
+
### fs — 文件系统
|
|
895
761
|
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
762
|
+
| 函数 | 描述 |
|
|
763
|
+
| -------------------- | -------------------------- |
|
|
764
|
+
| `scanDirectory` | 递归扫描目录,收集文件信息 |
|
|
765
|
+
| `writeJsonReport` | 将数据写入 JSON 文件 |
|
|
766
|
+
| `writeFileContent` | 写入文件内容 |
|
|
767
|
+
| `readFileContent` | 读取文件内容 |
|
|
768
|
+
| `fileExists` | 检查文件是否存在 |
|
|
769
|
+
| `checkSourceExists` | 检查源文件是否存在 |
|
|
770
|
+
| `ensureTargetDir` | 创建目标目录 |
|
|
771
|
+
| `copySourceToTarget` | 执行文件复制操作 |
|
|
772
|
+
| `runWithConcurrency` | 带并发限制的批量执行 |
|
|
773
|
+
|
|
774
|
+
```typescript
|
|
775
|
+
import { scanDirectory, writeJsonReport } from '@meng-xi/vite-plugin/common/fs'
|
|
776
|
+
|
|
777
|
+
const files = await scanDirectory('dist', {
|
|
778
|
+
includeExtensions: ['.js', '.css'],
|
|
779
|
+
excludePatterns: ['node_modules'],
|
|
780
|
+
filter: (filePath, ext, size) => size > 1024
|
|
781
|
+
})
|
|
782
|
+
|
|
783
|
+
await writeJsonReport('dist/report.json', { timestamp: Date.now(), files })
|
|
901
784
|
```
|
|
902
785
|
|
|
903
|
-
###
|
|
786
|
+
### html — HTML 注入
|
|
787
|
+
|
|
788
|
+
| 函数 | 描述 |
|
|
789
|
+
| ----------------------------- | ------------------------------- |
|
|
790
|
+
| `injectBeforeTag` | 在指定闭合标签前注入代码 |
|
|
791
|
+
| `injectHtmlByPriority` | 按优先级向 HTML 中注入代码 |
|
|
792
|
+
| `injectBeforeTagWithFallback` | 带回退策略的 HTML 注入 |
|
|
793
|
+
| `injectHeadAndBody` | 双区域 HTML 注入(head + body) |
|
|
904
794
|
|
|
905
795
|
```typescript
|
|
906
|
-
import {
|
|
907
|
-
import type { BasePluginOptions, PluginWithInstance } from '@meng-xi/vite-plugin/factory'
|
|
908
|
-
import type { Plugin } from 'vite'
|
|
796
|
+
import { injectBeforeTag, injectHeadAndBody } from '@meng-xi/vite-plugin/common/html'
|
|
909
797
|
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
798
|
+
const result = injectBeforeTag(html, '</head>', '<style>body{margin:0}</style>')
|
|
799
|
+
const dual = injectHeadAndBody(html, '<style>...</style>', '<script>...</script>')
|
|
800
|
+
```
|
|
913
801
|
|
|
914
|
-
|
|
915
|
-
protected getDefaultOptions() {
|
|
916
|
-
return { path: './default' }
|
|
917
|
-
}
|
|
802
|
+
### object — 对象操作
|
|
918
803
|
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
804
|
+
| 函数 | 描述 |
|
|
805
|
+
| ----------- | ------------ |
|
|
806
|
+
| `deepMerge` | 深度合并对象 |
|
|
922
807
|
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
}
|
|
808
|
+
```typescript
|
|
809
|
+
import { deepMerge } from '@meng-xi/vite-plugin/common/object'
|
|
926
810
|
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
this.logger.info(`Plugin started with path: ${this.options.path}`)
|
|
930
|
-
}
|
|
931
|
-
}
|
|
811
|
+
deepMerge({ a: { b: 1 } }, { a: { c: 2 } }) // { a: { b: 1, c: 2 } }
|
|
812
|
+
```
|
|
932
813
|
|
|
933
|
-
|
|
934
|
-
super.destroy()
|
|
935
|
-
// 自定义清理逻辑,如关闭连接、停止监听等
|
|
936
|
-
}
|
|
937
|
-
}
|
|
814
|
+
### path — 路径处理
|
|
938
815
|
|
|
939
|
-
|
|
940
|
-
|
|
816
|
+
| 函数 | 描述 |
|
|
817
|
+
| -------------- | --------------------------------- |
|
|
818
|
+
| `isNodeModule` | 判断模块 ID 是否来自 node_modules |
|
|
941
819
|
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
820
|
+
```typescript
|
|
821
|
+
import { isNodeModule } from '@meng-xi/vite-plugin/common/path'
|
|
822
|
+
|
|
823
|
+
isNodeModule('node_modules/lodash/index.js') // true
|
|
824
|
+
isNodeModule('src/utils/helper.ts') // false
|
|
945
825
|
```
|
|
946
826
|
|
|
947
|
-
|
|
827
|
+
### script — 脚本生成
|
|
948
828
|
|
|
949
|
-
|
|
829
|
+
| 函数 | 描述 |
|
|
830
|
+
| ------------------------ | ---------------------------------------- |
|
|
831
|
+
| `makeCallback` | 将回调函数体字符串包装为安全的函数表达式 |
|
|
832
|
+
| `containsScriptTag` | 检测字符串是否包含 `<script>` 标签 |
|
|
833
|
+
| `validateIdentifierName` | 验证字符串是否为合法的 JS 标识符 |
|
|
950
834
|
|
|
951
835
|
```typescript
|
|
952
|
-
|
|
953
|
-
import { buildProgress, copyFile, htmlInject, loadingManager, BasePlugin, Logger } from '@meng-xi/vite-plugin'
|
|
836
|
+
import { makeCallback, validateIdentifierName } from '@meng-xi/vite-plugin/common/script'
|
|
954
837
|
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
import { Validator, readFileContent, writeFileContent } from '@meng-xi/vite-plugin/common'
|
|
960
|
-
|
|
961
|
-
// 类型导入(从子路径按需导入类型定义)
|
|
962
|
-
import type { PluginWithInstance, PluginFactory, BasePluginOptions } from '@meng-xi/vite-plugin/factory'
|
|
963
|
-
import type { BuildProgressOptions, GenerateVersionOptions, VersionUpdateCheckerOptions, HtmlInjectOptions, InjectRule, FaviconManagerOptions, LoadingManagerOptions, Icon } from '@meng-xi/vite-plugin/plugins'
|
|
964
|
-
import type { DateFormatOptions } from '@meng-xi/vite-plugin/common/format'
|
|
965
|
-
import type { HtmlInjectResult, DualInjectResult } from '@meng-xi/vite-plugin/common/html'
|
|
966
|
-
import type { CopyOptions, CopyResult } from '@meng-xi/vite-plugin/common/fs'
|
|
838
|
+
makeCallback('console.log("done")')
|
|
839
|
+
// 'function() { try { console.log("done") } catch(e) { console.error("[callback] error:", e); } }'
|
|
840
|
+
|
|
841
|
+
validateIdentifierName('__APP_VERSION__') // 通过
|
|
967
842
|
```
|
|
968
843
|
|
|
969
|
-
|
|
844
|
+
### validation — 参数验证
|
|
970
845
|
|
|
971
|
-
|
|
846
|
+
| 函数 | 描述 |
|
|
847
|
+
| ---------------------------- | -------------------------- |
|
|
848
|
+
| `Validator` | 链式配置验证器类 |
|
|
849
|
+
| `validateGlobalName` | 验证全局变量名 |
|
|
850
|
+
| `validateNoScriptInTemplate` | 验证模板中不含 script 标签 |
|
|
851
|
+
| `validateCallbackFields` | 验证回调函数字段 |
|
|
852
|
+
| `validateNonNegativeNumber` | 验证非负数 |
|
|
853
|
+
| `validateNestedDuration` | 验证嵌套的时长配置 |
|
|
854
|
+
| `validateEnumValue` | 验证枚举值 |
|
|
972
855
|
|
|
973
|
-
|
|
856
|
+
```typescript
|
|
857
|
+
import { Validator } from '@meng-xi/vite-plugin/common/validation'
|
|
858
|
+
|
|
859
|
+
const validator = new Validator(options)
|
|
860
|
+
validator.field('port').number().minValue(1).maxValue(65535).validate()
|
|
861
|
+
```
|
|
862
|
+
|
|
863
|
+
---
|
|
974
864
|
|
|
975
|
-
|
|
865
|
+
## 子路径导出
|
|
976
866
|
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
867
|
+
| 子路径 | 描述 |
|
|
868
|
+
| ----------------------------------------------------- | ------------------------- |
|
|
869
|
+
| `@meng-xi/vite-plugin` | 主入口(所有插件+框架) |
|
|
870
|
+
| `@meng-xi/vite-plugin/factory` | 插件开发框架 |
|
|
871
|
+
| `@meng-xi/vite-plugin/logger` | 日志管理器 |
|
|
872
|
+
| `@meng-xi/vite-plugin/plugins` | 所有插件 |
|
|
873
|
+
| `@meng-xi/vite-plugin/common` | 所有工具函数 |
|
|
874
|
+
| `@meng-xi/vite-plugin/common/compress` | 压缩工具 |
|
|
875
|
+
| `@meng-xi/vite-plugin/common/format` | 格式化工具 |
|
|
876
|
+
| `@meng-xi/vite-plugin/common/fs` | 文件系统工具 |
|
|
877
|
+
| `@meng-xi/vite-plugin/common/html` | HTML 注入工具 |
|
|
878
|
+
| `@meng-xi/vite-plugin/common/object` | 对象操作工具 |
|
|
879
|
+
| `@meng-xi/vite-plugin/common/path` | 路径处理工具 |
|
|
880
|
+
| `@meng-xi/vite-plugin/common/script` | 脚本生成工具 |
|
|
881
|
+
| `@meng-xi/vite-plugin/common/validation` | 参数验证工具 |
|
|
882
|
+
| `@meng-xi/vite-plugin/plugins/build-progress` | buildProgress 插件 |
|
|
883
|
+
| `@meng-xi/vite-plugin/plugins/bundle-analyzer` | bundleAnalyzer 插件 |
|
|
884
|
+
| `@meng-xi/vite-plugin/plugins/compress-assets` | compressAssets 插件 |
|
|
885
|
+
| `@meng-xi/vite-plugin/plugins/copy-file` | copyFile 插件 |
|
|
886
|
+
| `@meng-xi/vite-plugin/plugins/favicon-manager` | faviconManager 插件 |
|
|
887
|
+
| `@meng-xi/vite-plugin/plugins/generate-router` | generateRouter 插件 |
|
|
888
|
+
| `@meng-xi/vite-plugin/plugins/generate-version` | generateVersion 插件 |
|
|
889
|
+
| `@meng-xi/vite-plugin/plugins/html-inject` | htmlInject 插件 |
|
|
890
|
+
| `@meng-xi/vite-plugin/plugins/loading-manager` | loadingManager 插件 |
|
|
891
|
+
| `@meng-xi/vite-plugin/plugins/version-update-checker` | versionUpdateChecker 插件 |
|
|
892
|
+
|
|
893
|
+
---
|
|
982
894
|
|
|
983
895
|
## License
|
|
984
896
|
|