版本:0.1.3 | 协议:MIT | 依赖:Vite ^5.0.0 || ^6.0.0 || ^7.0.0
写在前面
v0.1.3 的主题只有一个:让构建产物从"黑盒"变成"仪表盘"。
在此之前,你的 Vite 项目构建完成后,dist/ 目录里发生了什么——哪个 chunk 臃肿、哪个依赖膨胀、gzip 后实际传输多少——你一无所知。v0.1.3 带来的 bundleAnalyzer
插件,加上两个新工具模块和工具层增强,让你对构建产物拥有完全的量化能力。
如果你是老用户,升级只需一行;如果你是新读者,这篇文章会带你走完一个完整场景:从发现问题、量化问题、解决问题到自动化防控。
一、升级:一行改动,零风险
1.1 Breaking Changes
无。v0.1.3 完全向后兼容 v0.1.2。
1.2 升级方式
{
"devDependencies": {
"@meng-xi/vite-plugin": "^0.1.3"
}
}
1.3 新增能力速览
| bundleAnalyzer 插件 | 构建产物体积分析 + 报告 + 告警 + 对比 | 新增配置 |
| @common/compress 模块 | gzip 压缩大小计算 | 按需导入 |
| @common/path 模块 | 模块来源判断(node_modules / 虚拟模块) | 按需导入 |
| @common/format 增强 | escapeHtmlAttr、formatFileSize、getExtension | 按需导入 |
| @common/fs 增强 | scanDirectory、writeJsonReport + 2 个类型 | 按需导入 |
二、场景:一个真实项目的构建优化之旅
想象你是某个中型 Vite 项目的前端负责人。项目有 30+ 页面、50+ 依赖,构建后 dist/ 目录 5MB+。你隐约知道产物偏大,但缺乏数据支撑。以下是你从"盲区"到"全链路可见"的完整过程。
第一步:看见问题 — bundleAnalyzer 基础用法
import { bundleAnalyzer } from '@meng-xi/vite-plugin'
export default defineConfig({
plugins: [bundleAnalyzer()]
})
零配置启动。构建完成后,你立刻得到:
✅ [@meng-xi/vite-plugin:bundle-analyzer] 产物分析完成: 12 个 chunk, 总体积: 1.19MB (gzip: 384.21KB), 分析耗时: 156ms
入口: 2 | 代码块: 7 | 资源: 3
体积 Top 5 模块:
1. 234.57KB (node_modules) node_modules/lodash/lodash.js
2. 156.23KB (source) src/components/Dashboard.vue
3. 89.45KB (node_modules) node_modules/axios/index.js
4. 67.89KB (source) src/utils/api.ts
5. 45.12KB (source) src/views/Home.vue
关键发现:lodash 占了 234KB,而你可能只用了其中 3 个函数。
第二步:深入分析 — HTML 可视化报告
bundleAnalyzer({
outputFormat: 'both',
defaultChartType: 'treemap',
openAnalyzer: true
})
构建完成后自动打开浏览器,你看到三种视图:
| treemap | 矩形面积 = 体积占比,一眼定位大模块 | 快速扫描全局 |
| sunburst | 层级嵌套,模块→chunk→总体的包含关系 | 理解依赖层次 |
| list | 按体积排序的精确数值列表 | 精确对比、记录数据 |
第三步:设定防线 — 阈值告警
bundleAnalyzer({
sizeThreshold: 100
})
构建后自动检查:超过 100KB 的 chunk 🟡 普通告警,超过 200KB 的 🔴 严重告警。
⚠️ [@meng-xi/vite-plugin:bundle-analyzer] 发现 3 个体积告警:
🟡 chunk "vendor" 超过阈值: 156.3KB > 100KB
🔴 chunk "app" 严重超过阈值: 312.5KB > 100KB (2x)
🟡 chunk "utils" 超过阈值: 128.7KB > 100KB
从"感觉大"到"知道大多少",这是量化的第一步。
第四步:追踪变化 — 构建对比
你把 lodash 换成了 lodash-es,想确认体积是否真的减小了:
bundleAnalyzer({
compareWith: 'bundle-analysis-prev.json'
})
插件自动加载上次报告,逐模块对比:
| increased | 体积增大 |
| decreased | 体积减小 |
| unchanged | 体积不变 |
| added | 本次新增的模块 |
| removed | 本次移除的模块 |
ℹ️ [@meng-xi/vite-plugin:bundle-analyzer] 构建对比: 3 个增大, 2 个减小, 1 个新增, 0 个移除
从"改了"到"改了多少",这是量化的第二步。
第五步:压缩传输 — bundleAnalyzer + compressAssets 联合
bundleAnalyzer 帮你发现体积问题,compressAssets 帮你解决传输问题。两者天然互补:
import { defineConfig } from 'vite'
import { bundleAnalyzer, compressAssets, buildProgress, generateVersion } from '@meng-xi/vite-plugin'
export default defineConfig({
plugins: [
buildProgress({ format: 'bar' }),
generateVersion({ format: 'datetime', outputType: 'both' }),
bundleAnalyzer({
outputFormat: 'both',
sizeThreshold: 200,
topModules: 30,
gzipSize: true,
compareWith: 'bundle-analysis-prev.json',
defaultChartType: 'treemap'
}),
compressAssets({
algorithm: 'both',
threshold: 1024,
reportOutput: 'compress-report.json',
parallelLimit: 10
})
]
})
第六步:自动化防控 — CI/CD 集成
将体积检测写入 CI 流水线,每次 PR 自动检查:
// vite.config.ts — CI 环境
bundleAnalyzer({
outputFormat: 'json',
sizeThreshold: 100,
gzipSize: true,
compareWith: 'bundle-analysis-prev.json'
})
# CI 脚本
npm run build
node -e "
const report = require('./dist/bundle-analysis.json');
if (report.warnings.length > 0) {
console.error('体积告警:', report.warnings.map(w => w.message).join('; '));
process.exit(1);
}
"
从"事后发现"到"事前拦截",这是量化的终极形态。
三、bundleAnalyzer 工作原理
理解插件做了什么,才能用好它。
Vite 构建完成 (writeBundle, order: 'post')
↓
扫描 dist/ 目录,收集文件信息
↓
分析每个 chunk 的模块组成
↓
计算原始大小 + gzip 压缩大小(level: 9)
↓
生成 Top N 大模块排行
↓
按扩展名统计文件类型分布
↓
检查体积阈值,生成告警
↓
可选:与上次构建报告对比
↓
生成 JSON 报告和/或 HTML 可视化报告
可选:自动打开浏览器
输出分析摘要日志
三种报告格式各有侧重:
| json | bundle-analysis.json | CI/CD、自定义脚本、数据分析工具 |
| html | bundle-analysis.html | 开发者肉眼查看、团队分享、会议演示 |
| both | 同时生成两种 | 全都要 |
四、十大插件:从 0.0.6 到 0.1.3 的完整拼图
v0.1.3 补齐了构建产物分析这块拼图。十个插件,覆盖前端工程化的完整链路:
| buildProgress | 构建无进度反馈 | 终端可视化构建进度条 | 0.0.6 |
| bundleAnalyzer | 构建产物体积不可知 | 体积分析 + JSON/HTML 报告 + 阈值告警 + 对比 | 0.1.3 |
| compressAssets | 构建产物体积大 | gzip / brotli 压缩 + 报告 | 0.1.2 |
| copyFile | 静态资源全量复制 | 智能文件复制(增量 + 并发) | 0.0.6 |
| faviconManager | 图标管理繁琐 | 图标注入 + 文件复制一体化 | 0.0.9 |
| generateRouter | uni-app 路由手动维护 | pages.json 自动生成路由配置 | 0.0.6 |
| generateVersion | 版本号管理缺失 | 多格式版本号生成与注入 | 0.0.6 |
| htmlInject | HTML 内容注入缺乏统一方案 | 构建时 HTML 内容注入,支持条件/模板/安全过滤 | 0.1.1 |
| loadingManager | 白屏体验差 | 全局 Loading 状态管理 | 0.0.9 |
| versionUpdateChecker | 用户无法感知版本更新 | 运行时版本更新检测与提示 | 0.1.0 |
五、通用工具层:从重复实现到单一来源
5.1 问题:v0.1.2 的隐性债务
compressAssets 和 bundleAnalyzer 都需要 gzip 计算、目录扫描、文件大小格式化、扩展名提取、JSON 报告写入——各自实现了一遍。这不是代码量的问题,而是一致性风险:同一逻辑两份实现,修一个忘修另一个。
5.2 解法:v0.1.3 的工具层提取
v0.1.2 v0.1.3
┌──────────────────────────┐ ┌──────────────────────────────────┐
│ 9 个内置插件 │ │ 10 个内置插件 │
│ + bundleAnalyzer(新增) │ ──→ │ + bundleAnalyzer │
│ 各自实现压缩/扫描/格式化 │ │ 复用 @common 工具层 │
├──────────────────────────┤ ├──────────────────────────────────┤
│ 框架层 │ │ 框架层 │
│ BasePlugin · Validator │ │ BasePlugin · Validator · Logger │
├──────────────────────────┤ ├──────────────────────────────────┤
│ 工具层(6 个模块) │ │ 工具层(8 个模块) │
│ fs · format · html │ │ + compress(新增) │
│ object · script │ │ + path(新增) │
│ validation │ │ fs · format · html · object │
│ │ │ script · validation │
└──────────────────────────┘ └──────────────────────────────────┘
5.3 新增模块详解
@common/compress — 压缩算法
import { calculateGzipSize } from '@meng-xi/vite-plugin/common/compress'
const buffer = Buffer.from('some content to compress')
const gzipSize = await calculateGzipSize(buffer)
const stringData = 'another long string…'
const size = await calculateGzipSize(stringData)
| calculateGzipSize | data: Buffer | string | Promise<number> | 计算 gzip 压缩后大小,使用 level: 9 压缩 |
为什么用 level: 9? 分析场景追求的是估算网络传输的最小体积,而非压缩速度。用最高压缩级别,得到的是最保守(最小)的传输体积估算。
@common/path — 路径处理
import { isNodeModule } from '@meng-xi/vite-plugin/common/path'
isNodeModule('node_modules/lodash/index.js') // true
isNodeModule('src/utils/helper.ts') // false
isNodeModule('\\0some-virtual-module') // true — Rollup 内部虚拟模块
isNodeModule('virtual:import-meta-env') // true — 虚拟模块前缀
| isNodeModule | moduleId: string | boolean | 判断模块是否来自 node_modules,含虚拟模块检测 |
检测规则:
5.4 增强模块详解
@common/format — 新增三个函数
import { escapeHtmlAttr, formatFileSize, getExtension } from '@meng-xi/vite-plugin/common/format'
escapeHtmlAttr('hello "world"') // 'hello "world"'
escapeHtmlAttr('<script>') // '<script>'
formatFileSize(512) // '512B'
formatFileSize(1536) // '1.5KB'
formatFileSize(2461726) // '2.35MB'
getExtension('dist/app.js') // '.js'
getExtension('dist/style.CSS') // '.css'
| escapeHtmlAttr | str: string | string | 转义 HTML 属性值中的特殊字符,防止 XSS 注入 |
| formatFileSize | bytes: number | string | 字节数格式化为可读文件大小(xB / x.xKB / x.xxMB) |
| getExtension | filePath: string | string | 获取文件扩展名,返回小写(含点号,如 .js) |
formatFileSize 转换规则:
| < 1KB | xB | 512B |
| < 1MB | x.xKB | 1.5KB |
| ≥ 1MB | x.xxMB | 2.35MB |
@common/fs — 新增两个函数和两个类型
import { scanDirectory, writeJsonReport } from '@meng-xi/vite-plugin/common/fs'
import type { ScannedFile, ScanDirectoryOptions } from '@meng-xi/vite-plugin/common/fs'
const jsFiles = await scanDirectory('dist', { includeExtensions: ['.js'] })
const allFiles = await scanDirectory('dist', {
excludePatterns: ['node_modules', '.map'],
filter: (filePath, ext, size) => size > 1024
})
await writeJsonReport('dist/report.json', { timestamp: Date.now(), stats: [] })
await writeJsonReport('dist/report.json', data, 4)
| scanDirectory | 递归扫描目录,支持按扩展名、路径模式和自定义过滤函数过滤 |
| writeJsonReport | 将数据序列化为 JSON 并写入文件,默认缩进 2 空格 |
| ScannedFile | 扫描文件信息接口(filePath、size、extension) |
| ScanDirectoryOptions | 目录扫描选项接口(includeExtensions、excludePatterns、filter) |
scanDirectory 过滤优先级:
1. excludePatterns — 排除的路径模式(支持通配符前缀和子串匹配)
2. includeExtensions — 包含的扩展名(列表非空时生效)
3. filter — 自定义过滤函数(最终过滤)
5.5 工具层完整矩阵
| common/compress | calculateGzipSize | bundleAnalyzer、compressAssets |
| common/path | isNodeModule | bundleAnalyzer |
| common/format | formatFileSize、getExtension、escapeHtmlAttr | bundleAnalyzer、compressAssets |
| common/fs | scanDirectory、writeJsonReport | bundleAnalyzer、compressAssets |
| common/html | injectBeforeTag、injectHeadAndBody 等 | faviconManager、loadingManager、versionUpdateChecker |
| common/object | deepMerge | BasePlugin |
| common/script | makeCallback、containsScriptTag、validateIdentifierName | versionUpdateChecker、loadingManager |
| common/validation | Validator + 验证工具函数 | 所有插件 |
六、自定义插件:站在工具层的肩膀上
v0.1.3 的工具层不仅服务内置插件。你写自定义插件时,直接导入即可,不用重新实现目录扫描、gzip 计算、文件大小格式化这些通用逻辑。
示例:自定义产物统计插件
import { BasePlugin, createPluginFactory } from '@meng-xi/vite-plugin/factory'
import { scanDirectory, writeJsonReport } from '@meng-xi/vite-plugin/common/fs'
import { calculateGzipSize } from '@meng-xi/vite-plugin/common/compress'
import { formatFileSize, getExtension } from '@meng-xi/vite-plugin/common/format'
import { isNodeModule } from '@meng-xi/vite-plugin/common/path'
import type { Plugin } from 'vite'
interface AssetStatsOptions {
outputFile?: string
excludePatterns?: string[]
}
class AssetStatsPlugin extends BasePlugin<AssetStatsOptions> {
protected getPluginName() {
return 'asset-stats'
}
protected getDefaultOptions() {
return { outputFile: 'asset-stats.json', excludePatterns: [] }
}
protected addPluginHooks(plugin: Plugin): void {
plugin.writeBundle = {
order: 'post',
handler: async () => {
const outDir = this.viteConfig?.build.outDir
if (!outDir) return
const files = await scanDirectory(outDir, {
excludePatterns: this.options.excludePatterns
})
const stats = []
for (const file of files) {
const gzipSize = await calculateGzipSize(file.filePath)
stats.push({
path: file.filePath,
extension: getExtension(file.filePath),
size: formatFileSize(file.size),
gzipSize: formatFileSize(gzipSize),
isNodeModule: isNodeModule(file.filePath)
})
}
await writeJsonReport(this.options.outputFile!, { stats })
this.logger.success(`产物统计完成: ${files.length} 个文件`)
}
}
}
}
export const assetStats = createPluginFactory(AssetStatsPlugin)
你自动获得的能力:
| scanDirectory | @common/fs | 递归目录扫描 + 文件过滤 |
| calculateGzipSize | @common/compress | gzip 压缩流处理 |
| formatFileSize | @common/format | 字节数格式化逻辑 |
| getExtension | @common/format | 扩展名提取 + 小写转换 |
| isNodeModule | @common/path | node_modules + 虚拟模块检测 |
| writeJsonReport | @common/fs | JSON 序列化 + 文件写入 + 错误处理 |
七、实战配置:三种场景,三份配置
7.1 生产环境:分析 + 压缩 + 进度
import { defineConfig } from 'vite'
import { bundleAnalyzer, compressAssets, buildProgress, generateVersion } from '@meng-xi/vite-plugin'
export default defineConfig({
plugins: [
buildProgress({ format: 'bar' }),
generateVersion({ format: 'datetime', outputType: 'both' }),
bundleAnalyzer({
outputFormat: 'both',
outputFile: 'bundle-analysis',
sizeThreshold: 200,
topModules: 30,
gzipSize: true,
compareWith: 'bundle-analysis-prev.json',
defaultChartType: 'treemap'
}),
compressAssets({
algorithm: 'both',
threshold: 1024,
reportOutput: 'compress-report.json',
parallelLimit: 10
})
]
})
7.2 CI/CD:体积回归检测
import { bundleAnalyzer } from '@meng-xi/vite-plugin'
export default defineConfig({
plugins: [
bundleAnalyzer({
outputFormat: 'json',
sizeThreshold: 100,
gzipSize: true,
compareWith: 'bundle-analysis-prev.json'
})
]
})
CI 脚本:
npm run build
node -e "
const report = require('./dist/bundle-analysis.json');
if (report.warnings.length > 0) {
console.error('体积告警:', report.warnings.map(w => w.message).join('; '));
process.exit(1);
}
"
7.3 uni-app:条件启用
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import { bundleAnalyzer, compressAssets } from './uni_modules/vite-plugin/js_sdk/index.mjs'
export default defineConfig({
plugins: [
uni(),
bundleAnalyzer({
outputFormat: 'json',
sizeThreshold: 100,
gzipSize: true,
enabled: process.env.UNI_PLATFORM === 'h5' && process.env.VITE_USER_NODE_ENV === 'production'
}),
compressAssets({
algorithm: 'both',
threshold: 1024,
reportOutput: 'compress-report.json',
enabled: process.env.UNI_PLATFORM === 'h5' && process.env.VITE_USER_NODE_ENV === 'production'
})
]
})
八、通用工具模块速查
8.1 导入方式
// 全量导入
import { calculateGzipSize, isNodeModule, formatFileSize, scanDirectory } from '@meng-xi/vite-plugin/common'
// 按模块导入
import { calculateGzipSize } from '@meng-xi/vite-plugin/common/compress'
import { isNodeModule } from '@meng-xi/vite-plugin/common/path'
import { escapeHtmlAttr, formatFileSize, getExtension } from '@meng-xi/vite-plugin/common/format'
import { scanDirectory, writeJsonReport } from '@meng-xi/vite-plugin/common/fs'
8.2 完整子路径导出映射
| @meng-xi/vite-plugin | 全量导出(框架 + 插件 + 工具) |
| @meng-xi/vite-plugin/plugins | 10 个内置插件工厂函数 + 类型 |
| @meng-xi/vite-plugin/plugins/build-progress | buildProgress + 类型 |
| @meng-xi/vite-plugin/plugins/bundle-analyzer | bundleAnalyzer + 类型 |
| @meng-xi/vite-plugin/plugins/compress-assets | compressAssets + 类型 |
| @meng-xi/vite-plugin/plugins/copy-file | copyFile + 类型 |
| @meng-xi/vite-plugin/plugins/favicon-manager | faviconManager + 类型 |
| @meng-xi/vite-plugin/plugins/generate-router | generateRouter + 类型 |
| @meng-xi/vite-plugin/plugins/generate-version | generateVersion + 类型 |
| @meng-xi/vite-plugin/plugins/html-inject | htmlInject + 类型 |
| @meng-xi/vite-plugin/plugins/loading-manager | loadingManager + 类型 |
| @meng-xi/vite-plugin/plugins/version-update-checker | versionUpdateChecker + 类型 |
| @meng-xi/vite-plugin/factory | BasePlugin、createPluginFactory、PluginWithInstance |
| @meng-xi/vite-plugin/logger | Logger |
| @meng-xi/vite-plugin/common | 全部公共工具 |
| @meng-xi/vite-plugin/common/compress | calculateGzipSize |
| @meng-xi/vite-plugin/common/format | 日期格式化、模板解析、命名转换、文件大小格式化 |
| @meng-xi/vite-plugin/common/fs | 文件读写、复制、目录扫描、JSON 报告、并发控制 |
| @meng-xi/vite-plugin/common/html | HTML 注入工具 |
| @meng-xi/vite-plugin/common/object | deepMerge |
| @meng-xi/vite-plugin/common/path | isNodeModule |
| @meng-xi/vite-plugin/common/script | 回调包装、XSS 检测、标识符验证 |
| @meng-xi/vite-plugin/common/validation | Validator + 验证工具函数 |
九、详细 API 文档
9.1 通用配置(BasePluginOptions)
所有插件均继承自 BasePluginOptions,拥有以下通用配置:
| enabled | boolean | true | 是否启用插件 |
| verbose | boolean | true | 是否启用日志输出 |
| errorStrategy | 'throw' | 'log' | 'ignore' | 'throw' | 错误处理策略 |
9.2 bundleAnalyzer — 构建产物体积分析
在 Vite 构建(writeBundle)完成后自动扫描输出目录,分析构建产物的体积分布。
| outputFormat | 'json' | 'html' | 'both' | 'json' | 报告输出格式 |
| outputFile | string | 'bundle-analysis' | 报告输出文件名(不含扩展名) |
| openAnalyzer | boolean | false | 是否在生成 HTML 报告后自动打开浏览器 |
| sizeThreshold | number | 100 | 体积告警阈值(KB) |
| topModules | number | 20 | Top N 大模块排行数量 |
| compareWith | string | null | null | 用于对比的历史报告路径 |
| gzipSize | boolean | true | 是否计算 gzip 大小 |
| excludeNodeModules | boolean | false | 是否排除 node_modules 中的模块 |
| excludePatterns | string[] | [] | 需要排除的文件路径模式列表 |
| includeExtensions | string[] | [] | 需要包含的文件扩展名列表,为空则包含所有 |
| defaultChartType | 'treemap' | 'sunburst' | 'list' | 'treemap' | HTML 报告中图表的默认展示形式 |
导出类型:BundleAnalyzerOptions、BundleAnalysisResult、BundleOutputFormat、ChunkStats、ModuleStats、FileTypeDistribution、SizeWarning、ComparisonDiff
BundleAnalysisResult:
| timestamp | string | 分析时间戳(ISO 格式) |
| totalSize | number | 构建产物总大小(字节) |
| totalGzipSize | number | gzip 总大小(字节) |
| chunks | ChunkStats[] | chunk 统计列表 |
| topModules | ModuleStats[] | Top N 大模块 |
| fileTypeDistribution | FileTypeDistribution[] | 文件类型分布统计 |
| warnings | SizeWarning[] | 体积阈值告警列表 |
| comparisonDiffs | ComparisonDiff[] | 构建对比差异列表 |
| analysisTime | number | 分析耗时(毫秒) |
ChunkStats:
| name | string | chunk 名称 |
| size | number | 原始大小(字节) |
| gzipSize | number | gzip 压缩大小 |
| modules | ModuleStats[] | 包含的模块列表 |
| type | 'entry' | 'chunk' | 'asset' | chunk 类型 |
| fileCount | number | 包含的文件数量 |
ModuleStats:
| id | string | 模块标识符 |
| size | number | 模块原始大小(字节) |
| gzipSize | number | 模块 gzip 压缩后大小(字节) |
| chunks | string[] | 所属 chunk 名称列表 |
| imports | string[] | 依赖模块 ID 列表 |
| isEntry | boolean | 是否为入口模块 |
| isNodeModule | boolean | 是否来自 node_modules |
FileTypeDistribution:
| extension | string | 文件扩展名(如 .js) |
| count | number | 该类型的文件数量 |
| totalSize | number | 该类型的总大小(字节) |
| percentage | number | 该类型的总体积占比(0-100) |
SizeWarning:
| level | 'module' | 'chunk' | 告警级别 |
| name | string | 告警目标名称 |
| sizeKB | number | 实际大小(KB) |
| thresholdKB | number | 阈值大小(KB) |
| message | string | 告警消息 |
ComparisonDiff:
| name | string | 模块/chunk 名称 |
| previousSize | number | 上次构建大小 |
| currentSize | number | 本次构建大小 |
| diff | number | 体积变化量 |
| diffPercentage | number | 变化百分比 |
| trend | 'increased' | 'decreased' | 'unchanged' | 'added' | 'removed' | 变化趋势 |
9.3 compressAssets — 构建产物压缩
| algorithm | 'gzip' | 'brotli' | 'both' | 'gzip' | 压缩算法 |
| threshold | number | 1024 | 最小压缩阈值(字节) |
| deleteOriginalFile | boolean | false | 压缩后是否删除原始文件 |
| includeExtensions | string[] | ['.js', '.css', '.html', '.svg', '.json', '.xml', '.txt'] | 包含的扩展名 |
| excludeExtensions | string[] | [] | 排除的扩展名(优先级高于 include) |
| excludePaths | string[] | [] | 排除的路径前缀 |
| compressionLevel | number | 9 | gzip 压缩级别(1-9) |
| brotliQuality | number | 11 | brotli 质量参数(1-11) |
| reportOutput | string | false | 'compress-report.json' | 报告输出路径,false 不生成 |
| parallelLimit | number | 10 | 并发压缩的最大文件数 |
导出类型:CompressAssetsOptions、CompressAlgorithm、CompressStats、CompressSummary
9.4 buildProgress — 构建进度条
| width | number | 30 | 进度条宽度(字符数) |
| format | 'bar' | 'spinner' | 'minimal' | 'bar' | 显示格式 |
| completeChar | string | '█' | 已完成部分填充字符 |
| incompleteChar | string | '░' | 未完成部分填充字符 |
| clearOnComplete | boolean | true | 完成后是否清除进度条 |
| showModuleName | boolean | true | 是否显示当前模块名称 |
| theme | ProgressTheme | – | 自定义颜色主题 |
导出类型:BuildProgressOptions、ProgressFormat、BuildPhase、ProgressTheme
9.5 copyFile — 文件复制
| sourceDir | string | – | 源目录路径(必填) |
| targetDir | string | – | 目标目录路径(必填) |
| overwrite | boolean | true | 是否覆盖同名文件 |
| recursive | boolean | true | 是否递归复制子目录 |
| incremental | boolean | true | 是否启用增量复制 |
导出类型:CopyFileOptions
9.6 faviconManager — 图标管理
| base | string | – | 图标文件基础路径 |
| url | string | – | 图标完整 URL |
| link | string | – | 自定义完整 link 标签 |
| icons | HtmlTagDescriptor[] | – | 自定义图标数组 |
| copyOptions | object | – | 图标文件复制配置 |
导出类型:FaviconManagerOptions
9.7 generateRouter — 路由配置生成
| pagesJsonPath | string | 'src/pages.json' | pages.json 文件路径 |
| outputPath | string | 'src/router.config.ts' | 输出文件路径 |
| outputFormat | 'ts' | 'js' | 'ts' | 输出文件格式 |
| nameStrategy | 'path' | 'camelCase' | 'pascalCase' | 'custom' | 'camelCase' | 路由名称策略 |
| customNameGenerator | (path: string) => string | – | 自定义名称生成函数 |
| includeSubPackages | boolean | true | 是否包含子包路由 |
| watch | boolean | true | 是否监听 pages.json 变化 |
| metaMapping | Record<string, string> | {…} | 页面 style 到 meta 的映射 |
| exportTypes | boolean | true | 是否导出类型定义 |
| preserveRouteChanges | boolean | true | 是否保留用户修改 |
导出类型:GenerateRouterOptions、RouteConfig、RouteMeta、UniAppPagesJson、UniAppPageConfig、UniAppTabBarConfig、OutputFormat、NameStrategy
9.8 generateVersion — 版本号生成
| format | 'timestamp' | 'date' | 'datetime' | 'semver' | 'hash' | 'custom' | 'timestamp' | 版本号格式 |
| customFormat | string | – | 自定义格式模板 |
| semverBase | string | '1.0.0' | 语义化版本基础值 |
| outputType | 'file' | 'define' | 'both' | 'file' | 输出类型 |
| outputFile | string | 'version.json' | 输出文件路径 |
| defineName | string | '__APP_VERSION__' | 注入的全局变量名 |
| hashLength | number | 8 | 哈希长度(1-32) |
| prefix | string | – | 版本号前缀 |
| suffix | string | – | 版本号后缀 |
| extra | Record<string, any> | – | 附加信息 |
导出类型:GenerateVersionOptions
9.9 htmlInject — HTML 内容注入
| rules | HtmlInjectRule[] | – | 注入规则(必填) |
| targetFile | string | 'index.html' | 目标文件匹配 |
| security | SecurityConfig | – | 安全过滤配置 |
| templateVars | Record<string, string> | – | 全局模板变量 |
| logInjection | boolean | false | 是否记录注入日志 |
导出类型:HtmlInjectOptions、HtmlInjectRule、InjectPosition、InjectCondition、SecurityConfig、SelectorMatch
9.10 loadingManager — Loading 状态管理
| defaultVisible | boolean | true | 默认是否可见 |
| autoHideOn | string | 'DOMContentLoaded' | 自动隐藏时机 |
| spinnerType | string | 'circle' | Spinner 类型 |
| globalName | string | '__LOADING_MANAGER__' | 全局变量名 |
导出类型:LoadingManagerOptions
9.11 versionUpdateChecker — 版本更新检测
| versionSource | 'define' | 'file' | 'auto' | 'auto' | 版本来源 |
| checkInterval | number | 300000 | 检查间隔(毫秒) |
| promptStyle | 'modal' | 'banner' | 'toast' | 'modal' | 提示样式 |
| checkOnVisibilityChange | boolean | true | 标签页切回时是否检查 |
| enableInDev | boolean | false | 开发环境是否启用 |
导出类型:VersionUpdateCheckerOptions
十、路线图
短期
- bundleAnalyzer 支持 Webpack 兼容模式
- 构建产物趋势图(多版本体积变化折线图)
- 插件配置预设(web-app、uni-app、ssr)
中期
- 插件间事件总线
- 可视化配置生成器
- 社区插件市场
长期
成为 Vite 插件开发的标准框架——定义最佳实践,让社区以统一方式构建、分享和组合插件。
本文基于 @meng-xi/vite-plugin@0.1.3 版本撰写,所有代码示例均来自实际源码。

