@meng-xi/vite-plugin:Vite 实用插件工具包与开发框架
版本:0.1.1 | 协议:MIT | 依赖:Vite ^5.0.0 || ^6.0.0 || ^7.0.0

写在前面
在现代前端工程中,Vite 已经成为最流行的构建工具之一。然而,许多常见的工程化需求——构建进度可视化、静态资源复制、版本号管理、全局 Loading 状态管理、HTML 内容注入等——仍需要开发者自行编写脚本或引入多个零散的插件。@meng-xi/vite-plugin正是为解决这些痛点而生:它既是一个包含 8 个开箱即用插件的工具包,又是一个完整的插件开发框架,让你可以基于统一的规范快速构建自定义 Vite 插件。
本文将从核心功能、使用场景、安装配置、API 文档、代码示例、常见问题到版本历史,全面介绍这个包的方方面面。

一、核心功能介绍
1.1 双重定位:工具包 + 开发框架
@meng-xi/vite-plugin的独特之处在于它同时扮演两个角色:
定位 | 说明 | 目标用户 |
实用插件工具包 | 提供 8 个覆盖常见工程化场景的内置插件 | 所有 Vite 用户 |
插件开发框架 | 导出 BasePlugin、Logger、Validator 等核心组件 | 需要开发自定义 Vite 插件的开发者 |
1.2 八大内置插件一览
插件 | 解决的问题 | 一句话描述 | 引入版本 |
| 构建无进度反馈 | 终端可视化构建进度条 | 0.0.6 |
| 静态资源全量复制 | 智能文件复制(增量 + 并发) | 0.0.6 |
| uni-app 路由手动维护 | pages.json 自动生成路由配置 | 0.0.6 |
| 版本号管理缺失 | 多格式版本号生成与注入 | 0.0.6 |
| 图标管理繁琐 | 图标注入 + 文件复制一体化 | 0.0.9 |
| 白屏体验差 | 全局 Loading 状态管理 | 0.0.9 |
| 用户无法感知版本更新 | 运行时版本更新检测与提示 | 0.1.0 |
| HTML 内容注入缺乏统一方案 | 构建时 HTML 内容注入,支持条件/模板/安全过滤 | 0.1.1 |
1.3 插件开发框架核心组件
组件 | 说明 |
| 抽象基类,提供配置管理、日志记录、生命周期管理、安全执行等核心能力 |
| 工厂函数,将插件类转换为 Vite 插件实例,支持选项标准化 |
| 类型工具,为插件返回值提供 pluginInstance 的类型标注 |
| 单例日志管理器,统一管理所有插件的日志输出 |
| 流畅 API 验证器,支持链式调用验证插件配置 |
| 公共工具模块(fs、format、html、object、script、validation) |

二、使用场景分析
2.1 场景一:Vite Web 应用通用工程化
典型用户:使用 Vite 构建 SPA(React / Vue / Svelte)的开发者
痛点:
·构建时间长,但终端无进度反馈,不知道构建到哪一步了
·每次发版后用户仍在使用旧版本缓存,无法感知更新
·需要在 HTML 中注入 SEO meta 标签、第三方脚本,但手动编辑容易遗漏
·白屏时间无 Loading 提示,用户体验差
推荐插件组合:
import { defineConfig } from 'vite'
import { buildProgress, generateVersion, versionUpdateChecker, htmlInject, loadingManager, copyFile } from '@meng-xi/vite-plugin'
export default defineConfig({
plugins: [
buildProgress({ format: 'bar' }),
generateVersion({ format: 'datetime', outputType: 'both' }),
versionUpdateChecker({ checkInterval: 60000 }),
htmlInject({
rules: [{ id: 'meta-desc', content: '<meta name="description" content="My App">', position: 'head-end' }]
}),
loadingManager({ defaultVisible: true, autoHideOn: 'DOMContentLoaded' }),
copyFile({ sourceDir: 'public', targetDir: 'dist' })
]
})
2.2 场景二:uni-app 跨平台项目
典型用户:使用 HBuilderX 创建 uni-app 项目的开发者
痛点:
·pages.json 路由配置需要手动维护,容易遗漏或写错
·版本号管理困难,无法在运行时检测更新
·H5 平台需要 favicon 管理、HTML 注入等能力,但 uni-app 没有原生支持
推荐插件组合:
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import {
buildProgress, generateRouter, generateVersion,
htmlInject, faviconManager, loadingManager,
versionUpdateChecker, copyFile
} from '@meng-xi/vite-plugin'
export default defineConfig({
plugins: [
uni(),
buildProgress(),
generateRouter({ pagesJsonPath: 'pages.json' }),
generateVersion({ format: 'custom', customFormat: '{YYYY}.{MM}.{DD}-{hash}', outputType: 'both' }),
htmlInject({ rules: [...], enabled: process.env.UNI_PLATFORM === 'h5' }),
loadingManager({ defaultVisible: true, autoHideOn: 'DOMContentLoaded', enabled: process.env.UNI_PLATFORM === 'h5' }),
versionUpdateChecker({ enabled: process.env.UNI_PLATFORM === 'h5' && isProd }),
faviconManager({ enabled: process.env.UNI_PLATFORM === 'h5' && isProd }),
copyFile({ sourceDir: 'public', targetDir: 'dist/build/h5', enabled: process.env.UNI_PLATFORM === 'h5' && isProd })
]
})
2.3 场景三:开发自定义 Vite 插件
典型用户:需要开发团队内部 Vite 插件或开源 Vite 插件的开发者
痛点:
·每次开发插件都要从头搭建,日志、配置验证、错误处理等基础设施重复编写
·缺乏统一的插件规范,团队插件风格不一致
·插件配置类型安全难以保证
推荐方案:使用框架核心组件
import { BasePlugin, createPluginFactory } from '@meng-xi/vite-plugin/factory'
import type { BasePluginOptions } from '@meng-xi/vite-plugin/factory'
interface MyPluginOptions extends BasePluginOptions {
inputPath: string
outputPath: string
}
class MyPlugin extends BasePlugin<MyPluginOptions> {
protected getPluginName() {
return 'my-plugin'
}
protected getDefaultOptions() {
return { inputPath: './src', outputPath: './dist' }
}
protected validateOptions() {
this.validator.field('inputPath').required().string().validate()
}
protected addPluginHooks(plugin) {
plugin.buildStart = () => {
this.logger.info('构建开始')
}
}
}
export const myPlugin = createPluginFactory(MyPlugin)

三、安装与配置指南
3.1 安装
# npm
npm install @meng-xi/vite-plugin -D
# yarn
yarn add @meng-xi/vite-plugin -D
# pnpm
pnpm add @meng-xi/vite-plugin -D
3.2 前置要求
·Node.js >= 18.0.0
·Vite ^5.0.0 || ^6.0.0 || ^7.0.0(peerDependency)
3.3 导入方式
@meng-xi/vite-plugin支持多种导入路径,满足不同使用场景:
// 全量导入(8 个插件 + 框架组件)
import { buildProgress, copyFile, generateRouter, generateVersion, htmlInject, faviconManager, loadingManager, versionUpdateChecker, BasePlugin, createPluginFactory, Logger, Validator } from '@meng-xi/vite-plugin'
// 仅导入插件
import { htmlInject } from '@meng-xi/vite-plugin/plugins'
// 导入单个插件(最小化打包)
import { buildProgress } from '@meng-xi/vite-plugin/plugins/build-progress'
// 导入框架组件
import { BasePlugin, createPluginFactory, PluginWithInstance } from '@meng-xi/vite-plugin/factory'
// 导入日志
import { Logger } from '@meng-xi/vite-plugin/logger'
// 导入公共工具
import { deepMerge } from '@meng-xi/vite-plugin/common/object'
import { Validator } from '@meng-xi/vite-plugin/common/validation'
import { injectBeforeTag, injectHeadAndBody } from '@meng-xi/vite-plugin/common/html'
3.4 完整子路径导出映射
入口路径 | 导出内容 |
@meng-xi/vite-plugin | 全量导出(框架 + 插件) |
@meng-xi/vite-plugin/plugins | 8 个内置插件工厂函数 |
@meng-xi/vite-plugin/plugins/build-progress | buildProgress + 类型 |
@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/format | 日期格式化、模板解析、命名转换 |
@meng-xi/vite-plugin/common/fs | 文件读写、复制、并发控制 |
@meng-xi/vite-plugin/common/html | HTML 注入工具 |
@meng-xi/vite-plugin/common/object | deepMerge |
@meng-xi/vite-plugin/common/script | 回调包装、XSS 检测、标识符验证 |
@meng-xi/vite-plugin/common/validation | Validator + 验证工具函数 |

四、详细 API 文档
4.1 通用配置(BasePluginOptions)
所有插件均继承自 BasePluginOptions,拥有以下通用配置:
选项 | 类型 | 默认值 | 说明 |
enabled | boolean | true | 是否启用插件 |
verbose | boolean | true | 是否启用日志输出 |
errorStrategy | 'throw' | 'log' | 'ignore' | 'throw' | 错误处理策略 |
errorStrategy 详解:
·'throw':记录错误日志并抛出异常,中断构建(默认)
·'log':记录错误日志但不抛出异常,继续执行
·'ignore':与 'log' 行为一致,静默处理
4.2 buildProgress — 构建进度条
在终端实时显示 Vite 构建进度条,支持三种显示格式。
进度计算逻辑:
config (5%) → resolve (10%) → transform (15%-85%) → bundle (+10%) → write (+5%) → done (100%)
非 TTY 终端环境(如 CI/CD)自动降级为日志输出模式。
选项 | 类型 | 默认值 | 说明 |
width | number | 30 | 进度条宽度(字符数) |
format | 'bar' | 'spinner' | 'minimal' | 'bar' | 进度条显示格式 |
completeChar | string | '█' | 已完成部分的填充字符 |
incompleteChar | string | '░' | 未完成部分的填充字符 |
clearOnComplete | boolean | true | 构建完成后是否清除进度条 |
showModuleName | boolean | true | 是否显示当前正在处理的模块名称 |
theme | ProgressTheme | - | 自定义颜色主题 |
ProgressTheme 接口:
属性 | 类型 | 说明 |
completeColor | (text: string) => string | 已完成部分颜色渲染函数 |
incompleteColor | (text: string) => string | 未完成部分颜色渲染函数 |
percentageColor | (text: string) => string | 百分比数字颜色渲染函数 |
phaseColor | (text: string) => string | 阶段标签颜色渲染函数 |
moduleColor | (text: string) => string | 模块名称颜色渲染函数 |
导出类型:BuildProgressOptions、ProgressFormat、BuildPhase、ProgressTheme
4.3 copyFile — 文件复制
在 Vite 构建完成后(enforce: 'post')将指定源目录的文件复制到目标目录。
选项 | 类型 | 默认值 | 说明 |
sourceDir | string | - | 源目录路径(必填) |
targetDir | string | - | 目标目录路径(必填) |
overwrite | boolean | true | 是否覆盖同名文件 |
recursive | boolean | true | 是否递归复制子目录 |
incremental | boolean | true | 是否启用增量复制(比较修改时间和文件大小) |
增量复制模式下,仅当源文件修改时间晚于目标文件或文件大小不同时才执行复制,显著提升构建速度。
导出类型:CopyFileOptions
4.4 generateRouter — 路由配置生成
根据 uni-app 项目的 pages.json 自动生成路由配置文件,支持主包、子包和 tabBar 页面。
选项 | 类型 | 默认值 | 说明 |
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> | { navigationBarTitleText: 'title', requireAuth: 'requireAuth' } | 页面 style 字段到 meta 的映射 |
exportTypes | boolean | true | 是否导出类型定义 |
preserveRouteChanges | boolean | true | 是否保留用户对 routes 的修改 |
preserveRouteChanges 开启后,用户在生成的 routes 数组中手动修改的字段(如 meta 自定义属性)不会被覆盖。
导出类型:GenerateRouterOptions、RouteConfig、RouteMeta、UniAppPagesJson、UniAppPageConfig、UniAppTabBarConfig、OutputFormat、NameStrategy
4.5 generateVersion — 版本号生成
在 Vite 构建过程中自动生成版本号,支持多种格式和输出方式。
选项 | 类型 | 默认值 | 说明 |
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> | - | 附加信息(仅 JSON 文件) |
customFormat 占位符:
占位符 | 说明 | 示例 |
{YYYY} | 四位年份 | 2025 |
{MM} | 两位月份 | 01 |
{DD} | 两位日期 | 15 |
{HH} | 两位小时 | 14 |
{mm} | 两位分钟 | 30 |
{ss} | 两位秒数 | 45 |
{hash} | 随机哈希 | a3f8b2c1 |
{semver} | 语义化版本号 | 1.0.0 |
导出类型:GenerateVersionOptions、VersionFormat、VersionOutputType、VersionInfo
4.6 faviconManager — 图标管理
网站图标管理插件,支持将 favicon 注入到 HTML 并复制到输出目录。支持字符串简写配置。
选项 | 类型 | 默认值 | 说明 |
favicon | string | FaviconConfig | - | 图标路径或配置(必填) |
outputDir | string | - | 输出目录 |
inject | boolean | true | 是否注入 link 标签 |
copy | boolean | true | 是否复制文件到输出目录 |
导出类型:FaviconManagerOptions、FaviconConfig
4.7 loadingManager — 全局 Loading 管理
全局 Loading 状态管理插件,支持白屏 Loading、请求拦截、过渡动画等。
选项 | 类型 | 默认值 | 说明 |
defaultVisible | boolean | false | 是否默认显示 Loading |
autoHideOn | 'DOMContentLoaded' | 'load' | 'manual' | 'load' | 自动隐藏时机 |
style | LoadingStyle | - | Loading 样式配置 |
transition | TransitionConfig | - | 过渡动画配置 |
minDisplayTime | DurationConfig | - | 最小显示时间 |
delayShow | DurationConfig | - | 延迟显示配置 |
debounceHide | DurationConfig | - | 防抖隐藏配置 |
autoBind | 'fetch' | 'xhr' | 'all' | 'none' | 'all' | 自动绑定请求拦截 |
requestFilter | RequestFilterConfig | - | 请求过滤配置 |
导出类型:LoadingManagerOptions、LoadingStyle、TransitionConfig、DurationConfig、RequestFilterConfig、AutoBindType
4.8 versionUpdateChecker — 版本更新检测
运行时版本更新检测与提示插件,通常与 generateVersion 配合使用。
选项 | 类型 | 默认值 | 说明 |
versionSource | 'auto' | 'file' | 'define' | 'auto' | 版本号来源 |
versionFile | string | 'version.json' | 版本文件路径 |
defineName | string | '__APP_VERSION__' | 全局变量名 |
checkInterval | number | 60000 | 检查间隔(毫秒) |
promptStyle | 'modal' | 'banner' | 'toast' | 'modal' | 提示样式 |
onUpdateAvailable | string | - | 更新回调函数体字符串 |
导出类型:VersionUpdateCheckerOptions、VersionSource、PromptStyle
4.9 htmlInject — HTML 内容注入
在 Vite 构建过程中根据配置规则将 HTML 内容注入到目标文件中。
注入位置:
位置 | 说明 |
head-start | 注入到 <head> 标签开始后 |
head-end | 注入到 </head> 标签前 |
body-start | 注入到 <body> 标签开始后 |
body-end | 注入到 </body> 标签前 |
before-selector | 注入到选择器匹配内容前 |
after-selector | 注入到选择器匹配内容后 |
replace-selector | 替换选择器匹配的内容 |
选项 | 类型 | 默认值 | 说明 |
targetFile | string | 'index.html' | 目标 HTML 文件路径或文件名 |
rules | InjectRule[] | - | 注入规则数组(必填) |
security | SecurityConfig | - | 安全过滤配置 |
templateVars | Record<string, string> | - | 全局模板变量 |
logInjection | boolean | true | 是否输出注入日志 |
InjectRule 接口:
属性 | 类型 | 默认值 | 说明 |
id | string | - | 规则标识符(日志用) |
content | string | - | 要注入的 HTML 内容(必填) |
position | InjectPosition | - | 注入位置(必填) |
selector | string | - | 选择器字符串 |
priority | number | 100 | 优先级(数值越小越先执行) |
condition | InjectCondition | - | 注入条件 |
templateVars | Record<string, string> | - | 规则级模板变量(覆盖全局) |
allowScriptInjection | boolean | false | 是否允许注入脚本(跳过安全检查) |
SecurityConfig 接口:
属性 | 类型 | 默认值 | 说明 |
blockDangerousTags | boolean | true | 阻止危险标签(script、iframe、object 等) |
blockDangerousAttributes | boolean | true | 阻止危险属性(onclick、onload 等) |
allowedTags | string[] | [] | 标签白名单 |
blockedTags | string[] | [] | 自定义阻止标签 |
blockedAttributes | string[] | [] | 自定义阻止属性 |
导出类型:HtmlInjectOptions、InjectRule、InjectPosition、InjectCondition、ConditionType、SelectorMatch、SecurityConfig、InjectionLogEntry
4.10 插件开发框架 API
BasePlugin<T>
所有插件的抽象基类,提供以下核心能力:
方法/属性 | 说明 |
constructor(options, loggerConfig?) | 初始化配置、日志、验证器 |
getDefaultOptions() | 返回插件默认配置(可重写) |
mergeOptions(options) | 深度合并用户配置与默认配置 |
validateOptions() | 验证配置合法性(可重写) |
getPluginName() | 返回插件名称(抽象方法,必须实现) |
getEnforce() | 返回插件执行时机(可重写) |
addPluginHooks(plugin) | 添加 Vite 钩子(抽象方法,必须实现) |
onConfigResolved(config) | 配置解析完成回调 |
destroy() | 插件销毁回调(可重写) |
safeExecuteSync(fn, context) | 安全执行同步函数 |
safeExecute(fn, context) | 安全执行异步函数 |
handleError(error, context) | 根据 errorStrategy 处理错误 |
toPlugin() | 转换为 Vite 插件对象 |
options / logger / validator | 合并后的完整配置 / 日志代理 / 配置验证器 |
createPluginFactory<T, P, R>
创建插件工厂函数,将插件类转换为 Vite 插件实例。支持 normalizer 参数对原始配置进行标准化(如 faviconManager 支持字符串简写)。
Logger
单例日志管理器,统一管理所有插件的日志输出。
方法 | 说明 |
Logger.create(options) | 创建日志记录器(工厂方法) |
Logger.unregister(name) | 注销指定插件的日志配置 |
Logger.destroy() | 销毁单例实例 |
PluginLogger 接口(每个插件获得的日志代理):success(message, data?)、info(message, data?)、warn(message, data?)、error(message, data?)
Validator<T>
流畅 API 验证器,支持链式调用验证插件配置。
方法 | 说明 |
field(name) | 指定要验证的字段 |
required() | 标记为必填 |
string() / boolean() / number() / array() / object() | 验证类型 |
enum(values) | 验证枚举值 |
minValue(min) / maxValue(max) | 验证最小/最大值 |
default(value) | 设置默认值 |
custom(fn, message) | 自定义验证 |
validate() | 执行验证,失败时抛出错误 |
4.11 公共工具模块 API
模块 | 主要函数 |
common/format | padNumber、generateRandomHash、getDateFormatParams、formatDate、parseTemplate、toCamelCase、toPascalCase、stripJsonComments、escapeHtmlAttr |
common/fs | checkSourceExists、ensureTargetDir、readDirRecursive、shouldUpdateFile、fileExists、runWithConcurrency、copySourceToTarget、writeFileContent、readFileContent |
common/html | injectBeforeTag、injectHtmlByPriority、injectBeforeTagWithFallback、injectHeadAndBody |
common/object | deepMerge |
common/script | makeCallback、containsScriptTag、validateIdentifierName |
common/validation | validateGlobalName、validateNoScriptInTemplate、validateCallbackFields、validateNonNegativeNumber、validateNestedDuration、validateEnumValue |

五、代码示例
5.1 最小化配置
import { defineConfig } from 'vite'
import { buildProgress } from '@meng-xi/vite-plugin'
export default defineConfig({
plugins: [buildProgress()]
})
5.2 完整 Web 应用配置
import { defineConfig, loadEnv } from 'vite'
import { buildProgress, copyFile, generateVersion, htmlInject, loadingManager, versionUpdateChecker } from '@meng-xi/vite-plugin'
import type { PluginWithInstance } from '@meng-xi/vite-plugin/factory'
import type { GenerateVersionOptions } from '@meng-xi/vite-plugin/plugins/generate-version'
import type { LoadingManagerOptions } from '@meng-xi/vite-plugin/plugins/loading-manager'
import { resolve } from 'node:path'
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd())
const isProd = env.VITE_USER_NODE_ENV === 'production'
return {
plugins: [
buildProgress({ format: 'bar', width: 40 }),
generateVersion({
format: 'custom',
customFormat: '{YYYY}.{MM}.{DD}-{hash}',
hashLength: 6,
outputType: 'both',
defineName: '__APP_VERSION__',
prefix: 'v',
extra: { environment: isProd ? 'production' : 'development' }
}) as PluginWithInstance<GenerateVersionOptions>,
htmlInject({
rules: [
{
id: 'meta-description',
content: '<meta name="description" content="{{appName}} - My Application">',
position: 'head-end',
priority: 10,
templateVars: { appName: 'My App' }
},
{
id: 'analytics',
content: '<script src="/analytics.js"></script>',
position: 'body-end',
condition: { type: 'env', value: 'PRODUCTION' },
allowScriptInjection: true
}
],
security: { blockDangerousTags: true, blockDangerousAttributes: true },
logInjection: true
}),
loadingManager({
defaultVisible: true,
autoHideOn: 'DOMContentLoaded',
style: {
overlayColor: 'rgba(255, 255, 255, 0.85)',
spinnerColor: '#4361ee',
backdropBlur: true,
backdropBlurAmount: 3
},
transition: { enabled: true, duration: 300, easing: 'ease-out' },
minDisplayTime: { enabled: true, duration: 500 },
delayShow: { enabled: true, duration: 200 },
debounceHide: { enabled: true, duration: 100 },
autoBind: 'all',
requestFilter: { excludeUrlPrefixes: ['/static/', '/api/health'] }
}) as PluginWithInstance<LoadingManagerOptions>,
versionUpdateChecker({
versionSource: 'auto',
defineName: '__APP_VERSION__',
checkInterval: 60000,
promptStyle: 'modal',
onUpdateAvailable: 'console.log("[Update]", currentVersion, "→", newVersion); return true;'
}),
copyFile({
sourceDir: resolve('public'),
targetDir: resolve('dist'),
overwrite: true,
incremental: true
})
]
}
})
5.3 访问插件实例
import { generateVersion, loadingManager } from '@meng-xi/vite-plugin'
import type { PluginWithInstance } from '@meng-xi/vite-plugin/factory'
import type { GenerateVersionOptions } from '@meng-xi/vite-plugin/plugins/generate-version'
import type { LoadingManagerOptions } from '@meng-xi/vite-plugin/plugins/loading-manager'
const versionPlugin = generateVersion({
format: 'datetime',
outputType: 'both'
}) as PluginWithInstance<GenerateVersionOptions>
const loadingPlugin = loadingManager({
defaultVisible: true,
autoHideOn: 'DOMContentLoaded'
}) as PluginWithInstance<LoadingManagerOptions>
// 通过 pluginInstance 访问插件内部状态
console.log(versionPlugin.pluginInstance?.options)
console.log(loadingPlugin.pluginInstance?.options)
5.4 自定义插件开发
import { BasePlugin, createPluginFactory } from '@meng-xi/vite-plugin/factory'
import type { BasePluginOptions, PluginWithInstance } from '@meng-xi/vite-plugin/factory'
import type { Plugin } from 'vite'
interface SitemapOptions extends BasePluginOptions {
baseUrl: string
outputDir: string
excludePaths?: string[]
}
class SitemapPlugin extends BasePlugin<SitemapOptions> {
protected getPluginName(): string { return 'sitemap-generator' }
protected getDefaultOptions(): Partial<SitemapOptions> {
return {
baseUrl: 'https://example.com',
outputDir: 'dist',
excludePaths: ['/404', '/admin']
}
}
protected validateOptions(): void {
this.validator.field('baseUrl').required().string()
.field('outputDir').required().string().validate()
}
protected addPluginHooks(plugin: Plugin): void {
plugin.writeBundle = async () => {
await this.safeExecute(async () => {
this.logger.info('正在生成 sitemap...')
// ... 生成逻辑
this.logger.success('sitemap.xml 已生成')
}, '生成 sitemap')
}
}
}
export const sitemapGenerator = createPluginFactory(SitemapPlugin)
5.5 运行时 Loading 控制
// 在应用代码中控制 Loading
const manager = window.__LOADING_MANAGER__
// 显示
manager.show('正在加载数据...')
// 隐藏
manager.hide()
// 强制隐藏(忽略最小显示时间)
manager.forceHide()
// 更新文本
manager.updateText('正在处理数据...')
// 检查状态
if (manager.isVisible()) {
console.log('Loading 正在显示')
}
// 获取挂起请求数
console.log('当前请求数:', manager.getPendingCount())
// 切换指针事件
manager.disablePointerEvents() // 允许穿透点击
manager.enablePointerEvents()// 阻止穿透点击

六、常见问题解答
Q1:插件之间有依赖关系吗?
大部分插件是独立的,但 versionUpdateChecker通常需要与 generateVersion配合使用——前者读取后者生成的版本号文件或全局变量。其他插件可以单独使用,互不依赖。
Q2:如何在 uni-app 项目中使用?
uni-app 项目中需要注意平台限制。htmlInject、loadingManager、versionUpdateChecker等依赖 DOM API 的插件仅在 H5 平台生效,应通过 enabled选项控制:
htmlInject({ rules: [...], enabled: process.env.UNI_PLATFORM === 'h5' })
loadingManager({ ..., enabled: process.env.UNI_PLATFORM === 'h5' })
同时,HBuilderX 创建的项目没有 src/目录,generateRouter的 pagesJsonPath应配置为 'pages.json'。
Q3:loadingManager 的 defaultVisible 和 autoHideOn 如何配合?
·defaultVisible: true + autoHideOn: 'DOMContentLoaded':白屏即显示 Loading,DOM 解析完成后自动隐藏(适合 SSR/MPA)
·defaultVisible: true + autoHideOn: 'load':白屏即显示,所有资源加载完成后自动隐藏(适合资源较重的页面)
·defaultVisible: true + autoHideOn: 'manual':白屏即显示,需在应用代码中手动调用 window.__LOADING_MANAGER__.hide()(适合 Vue/React SPA)
Q4:htmlInject 如何安全地注入第三方脚本?
默认情况下,htmlInject会阻止 <script>标签的注入。如果你确认来源可信,可以在规则级别设置 allowScriptInjection: true:
{
id: 'google-analytics',
content: '<script src="https://www.googletagmanager.com/gtag/js?id=GA_ID"></script>',
position: 'body-end',
condition: { type: 'env', value: 'PRODUCTION' },
allowScriptInjection: true// 跳过安全检查
}
Q5:如何关闭某个插件的日志?
设置 verbose: false即可关闭该插件的所有日志输出:
buildProgress({ verbose: false })
copyFile({ sourceDir: 'src/assets', targetDir: 'dist/assets', verbose: false })
Q6:generateRouter 生成的路由配置会被覆盖吗?
默认情况下 preserveRouteChanges: true,插件会保留用户对 routes 数组中字段的修改(如自定义 meta 属性)。仅 path字段始终使用 pages.json中的值,因为它是路由标识符。
Q7:copyFile 的增量复制是如何判断的?
增量复制模式下,插件会比较源文件和目标文件的修改时间(mtimeMs)和文件大小(size)。只有当源文件修改时间晚于目标文件,或文件大小不同时,才执行复制。
Q8:如何在 CI/CD 环境中使用 buildProgress?
buildProgress会自动检测终端类型。在非 TTY 环境(如 CI/CD)下,进度条自动降级为日志输出模式,不会出现乱码。
Q9:插件加载顺序有要求吗?
Vite 插件的执行顺序由 enforce属性决定。copyFile设置了 enforce: 'post',确保在所有其他插件之后执行。其他插件使用默认顺序。如果你有自定义插件依赖本包插件的输出,请注意配置顺序。
Q10:如何开发自己的 Vite 插件并复用本包的公共工具?
// 直接导入公共工具
import { deepMerge } from '@meng-xi/vite-plugin/common/object'
import { Validator } from '@meng-xi/vite-plugin/common/validation'
import { injectBeforeTag } from '@meng-xi/vite-plugin/common/html'
import { writeFileContent, readFileContent } from '@meng-xi/vite-plugin/common/fs'
import { makeCallback, containsScriptTag } from '@meng-xi/vite-plugin/common/script'
// 或继承 BasePlugin 开发完整插件
import { BasePlugin, createPluginFactory } from '@meng-xi/vite-plugin/factory'

七、版本更新历史
v0.1.1(当前版本)
新增:
·htmlInject插件:构建时 HTML 内容注入,支持条件注入、模板变量、安全过滤
·PluginWithInstance类型导出:为插件返回值提供 pluginInstance的类型标注
·uni-app 全插件集成:8 个插件全部适配 HBuilderX 项目
改进:
·完善子路径导出,支持按需导入单个插件
v0.1.0
新增:
·versionUpdateChecker插件:运行时版本更新检测与提示
·支持三种提示样式(modal / banner / toast)
·页面可见性变化时自动检查更新
v0.0.9
新增:
·faviconManager插件:网站图标管理,支持注入和文件复制
·loadingManager插件:全局 Loading 状态管理
·支持请求拦截(fetch / XHR / all)
·支持白屏 Loading(defaultVisible + autoHideOn)
v0.0.7
改进:
·完善插件文档和使用指南
·优化插件配置验证
v0.0.6
初始发布:
·buildProgress插件:终端构建进度条
·copyFile插件:文件复制(增量 + 并发)
·generateRouter插件:uni-app 路由配置生成
·generateVersion插件:版本号生成与注入
·BasePlugin抽象基类
·createPluginFactory工厂函数
·Logger单例日志管理器
·Validator流畅 API 验证器
·公共工具模块(fs、format、html、object、script、validation)

八、架构设计
8.1 整体架构
@meng-xi/vite-plugin
├── factory/# 插件开发框架
│├── BasePlugin# 抽象基类
│├── createPluginFactory# 工厂函数
│└── types# 类型定义
├── logger/# 日志系统
│└── Logger# 单例日志管理器
├── common/# 公共工具
│├── fs# 文件系统操作
│├── format# 格式化工具
│├── html# HTML 注入工具
│├── object# 对象操作
│├── script# 脚本安全工具
│└── validation# 验证工具
└── plugins/# 内置插件
├── buildProgress
├── copyFile
├── faviconManager
├── generateRouter
├── generateVersion
├── htmlInject
├── loadingManager
└── versionUpdateChecker
8.2 插件生命周期
创建插件实例
│
▼
constructor()
├── mergeOptions()# 合并配置
├── initLogger()# 初始化日志
└── validateOptions()# 验证配置
│
▼
toPlugin() → Vite Plugin
│
▼
configResolved()# Vite 配置解析完成
│
▼
addPluginHooks() 注册的钩子# 构建过程中执行
│
▼
closeBundle()# 构建结束
│
▼
destroy()# 插件销毁,清理资源
8.3 错误处理策略
错误发生
│
├── errorStrategy: 'throw'→ 记录日志 + 抛出异常(中断构建)
├── errorStrategy: 'log'→ 记录日志 + 返回 undefined(继续执行)
└── errorStrategy: 'ignore' → 记录日志 + 返回 undefined(继续执行)

本文基于 @meng-xi/vite-plugin@0.1.1 版本撰写,所有代码示例均来自实际源码与项目配置。
夜雨聆风