一站式 Vite 插件工具库,5 个开箱即用的构建增强插件 + 完整的插件开发框架。无论你是想快速提升构建体验,还是开发自己的 Vite 插件,@meng-xi/vite-plugin 都能为你提供优雅的解决方案。


📑 目录


一、项目概览

@meng-xi/vite-plugin 是一个双用途的 Vite 生态工具库:

能力说明
开箱即用的插件集5 个精心设计的构建增强插件,覆盖进度可视化、文件复制、版本管理、路由生成、图标注入等常见需求
插件开发框架基于 BasePlugin 抽象类的完整开发体系,提供配置管理、日志记录、错误处理、生命周期管理等基础设施

核心设计原则

  • 零配置可用 — 每个插件都有合理的默认值,一行代码即可启用
  • 灵活可定制 — 丰富的配置选项和钩子,满足不同场景需求
  • 类型安全 — 完整的 TypeScript 类型定义,IDE 智能提示友好
  • 错误容错 — 三级错误策略(throw / log / ignore),安全执行机制
  • 框架一致性 — 所有插件遵循统一的 BasePlugin 规范,API 风格一致

包信息

{
	"name": "@meng-xi/vite-plugin",
	"version": "0.0.7",
	"type": "module",
	"peerDependencies": { "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" }
}

二、快速开始

安装

# pnpm(推荐)
pnpm add @meng-xi/vite-plugin -D

# npm
npm install @meng-xi/vite-plugin -D

# yarn
yarn add @meng-xi/vite-plugin -D

最小配置

import { defineConfig } from 'vite'
import { buildProgress, copyFile, generateVersion, injectIco } from '@meng-xi/vite-plugin'

export default defineConfig({
	plugins: [
		buildProgress(), // 构建进度条
		copyFile({
			// 文件复制
			sourceDir: 'public',
			targetDir: 'dist'
		}),
		generateVersion(), // 版本号生成
		injectIco() // 图标注入
	]
})

按需导入

通过子路径导出,只引入需要的模块:

// 仅导入插件
import { buildProgress } from '@meng-xi/vite-plugin/plugins'

// 仅导入工具函数
import { deepMerge, formatDate } from '@meng-xi/vite-plugin/common'

// 仅导入框架(开发自定义插件)
import { BasePlugin, createPluginFactory } from '@meng-xi/vite-plugin/factory'

// 仅导入日志
import { Logger } from '@meng-xi/vite-plugin/logger'

三、插件详解

3.1 buildProgress — 构建进度条

在终端实时显示 Vite 构建进度,告别"黑盒等待"。

三种显示格式
# bar(默认)— 完整进度条
⠋ 转换模块 ██████████████████████░░░░░░░░ 67% src/components/App.vue

# spinner — 旋转动画
⠹ 转换模块 67% src/components/App.vue

# minimal — 精简模式
转换模块 67%
使用示例
// 默认配置
buildProgress()

// 自定义外观
buildProgress({
	format: 'bar',
	width: 40,
	completeChar: '■',
	incompleteChar: '□',
	clearOnComplete: false
})

// 自定义颜色主题(使用 picocolors)
import pc from 'picocolors'
buildProgress({
	theme: {
		completeColor: pc.green,
		incompleteColor: pc.gray,
		percentageColor: pc.bold,
		phaseColor: pc.cyan,
		moduleColor: pc.yellow
	}
})

// CI 环境使用精简模式
buildProgress({
	format: process.env.CI ? 'minimal' : 'bar',
	enabled: process.env.CI !== 'true'
})
进度计算模型
阶段进度说明
config5%读取配置
resolve10%解析模块依赖
transform15%-85%转换模块(按比例线性计算)
bundle+10%打包(仅生产构建)
write+5%写入文件
done100%构建完成

关键设计:进度只进不退,通过 lastPercentage 缓存避免视觉闪烁。

配置参数
参数类型默认值说明
widthnumber30进度条宽度(字符数)
format'bar' | 'spinner' | 'minimal''bar'显示格式
completeCharstring'█'已完成填充字符
incompleteCharstring'░'未完成填充字符
clearOnCompletebooleantrue完成后是否清除进度条
showModuleNamebooleantrue是否显示当前模块名
themeProgressTheme自定义颜色主题

3.2 copyFile — 文件复制

构建完成后将指定目录的文件复制到目标位置,支持增量更新。

使用示例
// 基本使用
copyFile({
	sourceDir: 'public',
	targetDir: 'dist/build/h5'
})

// 高级配置
copyFile({
	sourceDir: resolve('public'),
	targetDir: resolve('dist/build/h5'),
	overwrite: true,
	recursive: true,
	incremental: true, // 仅复制修改过的文件
	enabled: isH5 && isProd
})
核心特性
  • 增量复制 — 通过比较文件修改时间和大小,仅复制有变化的文件
  • 并行 IO — 使用并发控制(默认 10 路)加速大批量文件复制
  • 递归支持 — 可选递归复制子目录
  • 覆盖控制 — 可配置是否覆盖同名文件
配置参数
参数类型默认值说明
sourceDirstring必填,源目录路径
targetDirstring必填,目标目录路径
overwritebooleantrue是否覆盖同名文件
recursivebooleantrue是否递归复制子目录
incrementalbooleantrue是否启用增量复制

3.3 generateVersion — 版本号生成

自动生成版本号,支持多种格式和输出方式。

使用示例
// 时间戳格式(默认)
generateVersion()

// 日期格式
generateVersion({ format: 'date' })

// 语义化版本 + 前缀
generateVersion({
	format: 'semver',
	semverBase: '2.0.0',
	prefix: 'v'
})

// 自定义格式
generateVersion({
	format: 'custom',
	customFormat: '{YYYY}.{MM}.{DD}-{hash}',
	hashLength: 6
})

// 同时输出文件和注入全局变量
generateVersion({
	format: 'datetime',
	outputType: 'both',
	defineName: '__APP_VERSION__',
	extra: {
		environment: 'production',
		author: 'MengXi Studio'
	}
})
版本格式一览
格式示例输出说明
timestamp20260520153000时间戳(默认)
date2026.05.20日期
datetime2026.05.20.153000日期时间
semver1.0.0语义化版本
hasha1b2c3d4随机哈希
custom自定义配合 customFormat 使用
自定义格式占位符

customFormat 支持以下占位符:{YYYY}{YY}{MM}{DD}{HH}{mm}{ss}{SSS}{timestamp}{hash}{major}{minor}{patch}

输出类型
  • file — 写入 JSON 文件到构建输出目录
  • define — 通过 Vite define 注入全局变量,可在代码中直接使用
  • both — 两种方式同时启用

在代码中使用注入的版本号:

// 需要在 vite-env.d.ts 中声明类型
declare const __APP_VERSION__: string
declare const __APP_VERSION___INFO: { version: string; buildTime: string; timestamp: number }

console.log(__APP_VERSION__) // 'v2026.05.20-a1b2c3'
console.log(__APP_VERSION___INFO) // { version: '...', buildTime: '...', ... }

3.4 generateRouter — 路由配置生成

读取 uni-app 项目的 pages.json,自动生成路由配置文件。

使用示例
// 默认配置
generateRouter()

// 自定义路径
generateRouter({
	pagesJsonPath: 'pages.json',
	outputPath: 'src/router.config.ts'
})

// 输出 JavaScript
generateRouter({
	outputFormat: 'js',
	outputPath: 'src/router.config.js'
})

// 自定义路由名称策略
generateRouter({
	nameStrategy: 'pascalCase' // 或 'camelCase' | 'path' | 'custom'
})

// 自定义名称生成函数
generateRouter({
	nameStrategy: 'custom',
	customNameGenerator: path => `route_${path.replace(/\//g, '_')}`
})

// 自定义元信息映射
generateRouter({
	metaMapping: {
		navigationBarTitleText: 'title',
		requireAuth: 'requireAuth',
		customField: 'custom'
	}
})
核心特性
  • 主包 + 子包 — 自动解析主包和 subPackages 中的页面
  • TabBar 识别 — 自动标记 tabBar 页面(meta.isTab = true
  • 名称策略 — 支持 pathcamelCasepascalCasecustom 四种命名策略
  • 元信息映射 — 可自定义 pages.json style 字段到路由 meta 的映射
  • 变更保留preserveRouteChanges 开启后,用户对路由的手动修改不会被覆盖
  • 文件监听 — 开发模式下自动监听 pages.json 变化并重新生成
  • 类型导出 — 自动生成 RouteConfigRouteMeta 等类型定义
生成的文件示例
// src/router.config.ts(自动生成)
export interface RouteMeta {
	title?: string
	isTab?: boolean
	requireAuth?: boolean
	[key: string]: unknown
}

export interface RouteConfig {
	path: string
	name?: string
	meta?: RouteMeta
}

export const routes: RouteConfig[] = [
	{ path: '/pages/index/index', name: 'pagesIndex', meta: { title: '首页', isTab: true } },
	{ path: '/pages/user/profile', name: 'pagesUserProfile', meta: { title: '个人中心' } }
]

export default routes

3.5 injectIco — 图标注入

将网站图标链接注入到 HTML 的 <head> 中,并可选复制图标文件。

使用示例
// 最简配置
injectIco()

// 指定 base 路径(字符串简写)
injectIco('/assets')

// 完整配置
injectIco({
	base: '/assets',
	icons: [
		{ rel: 'icon', href: '/favicon.svg', type: 'image/svg+xml' },
		{ rel: 'icon', href: '/favicon-32x32.png', sizes: '32x32', type: 'image/png' },
		{ rel: 'apple-touch-icon', href: '/apple-touch-icon.png', sizes: '180x180' }
	],
	copyOptions: {
		sourceDir: 'public',
		targetDir: 'dist/build/h5',
		overwrite: true,
		recursive: true
	}
})

// 使用外部 URL
injectIco({
	url: 'https://cdn.example.com/favicon.ico'
})

// 自定义完整 link 标签
injectIco({
	link: '<link rel="icon" href="/favicon.svg" type="image/svg+xml" />'
})
优先级

link > url > base + favicon.ico

当提供 link 时,其他选项被忽略;当提供 url 时,base 被忽略。


四、核心框架:BasePlugin 开发体系

4.1 架构设计

┌─────────────────────────────────────────────────────┐
│                    BasePlugin<T>                     │
│  (抽象基类,提供插件开发的所有基础设施)                │
├─────────────────────────────────────────────────────┤
│  配置管理    mergeOptions + getDefaultOptions        │
│  参数验证    validateOptions + Validator             │
│  日志记录    Logger (单例) + PluginLogger (代理)      │
│  错误处理    safeExecute / safeExecuteSync           │
│  生命周期    onConfigResolved / destroy              │
│  Vite 桥接   toPlugin() → Plugin 对象               │
├─────────────────────────────────────────────────────┤
│  子类实现                                            │
│  getPluginName()    — 插件名称(抽象)               │
│  addPluginHooks()   — 注册 Vite 钩子(抽象)         │
│  getDefaultOptions()— 插件默认配置(可选重写)        │
│  validateOptions()  — 自定义验证(可选重写)          │
│  destroy()          — 清理逻辑(可选重写)            │
└─────────────────────────────────────────────────────┘
         │
         ▼ createPluginFactory()
┌─────────────────────────────────────────────────────┐
│  PluginFactory<T, R>                                │
│  (options?) => PluginWithInstance<T>                │
│  · 支持选项标准化器(OptionsNormalizer)              │
│  · 返回的 Plugin 对象附带 pluginInstance 属性        │
└─────────────────────────────────────────────────────┘

4.2 BasePlugin 抽象类

BasePlugin 是所有插件的基类,提供了完整的插件开发基础设施:

abstract class BasePlugin<T extends BasePluginOptions> {
	// ===== 子类必须实现 =====
	protected abstract getPluginName(): string
	protected abstract addPluginHooks(plugin: Plugin): void

	// ===== 子类可选重写 =====
	protected getDefaultOptions(): Partial<T> // 插件默认配置
	protected validateOptions(): void // 配置验证
	protected destroy(): void // 清理逻辑
	protected onConfigResolved(config: ResolvedConfig) // 配置解析回调

	// ===== 框架提供的能力 =====
	protected options: Required<T> // 合并后的配置
	protected logger: PluginLogger // 日志代理
	protected validator: Validator<T> // 参数验证器
	protected safeExecute<T>(fn, context): Promise<T> // 安全异步执行
	protected safeExecuteSync<T>(fn, context): T // 安全同步执行
	protected handleError<T>(error, context): T // 错误处理
	public toPlugin(): Plugin // 转换为 Vite 插件
}
通用配置(BasePluginOptions)

所有插件都继承以下基础配置:

interface BasePluginOptions {
	enabled?: boolean // 是否启用,默认 true
	verbose?: boolean // 是否输出日志,默认 true
	errorStrategy?: 'throw' | 'log' | 'ignore' // 错误策略,默认 'throw'
}
错误处理策略
策略行为
throw记录错误日志并抛出异常,中断构建
log记录错误日志但不中断,返回 undefined
ignorelog,静默处理

4.3 createPluginFactory 工厂函数

将插件类转换为符合 Vite 规范的工厂函数:

// 基本用法
const myPlugin = createPluginFactory(MyPluginClass)

// 带选项标准化器(支持字符串简写)
const injectIco = createPluginFactory<InjectIcoOptions, InjectIcoPlugin, string | InjectIcoOptions>(InjectIcoPlugin, options => (typeof options === 'string' ? { base: options } : options || {}))

返回的 PluginWithInstance 对象包含 pluginInstance 属性,可访问插件内部状态:

const progress = buildProgress() as PluginWithInstance<BuildProgressOptions>
console.log(progress.pluginInstance?.options)

4.4 自定义插件开发实战

以下是一个完整的自定义插件示例 — 构建耗时统计插件:

import { BasePlugin, createPluginFactory } from '@meng-xi/vite-plugin/factory'
import type { BasePluginOptions } from '@meng-xi/vite-plugin/factory'
import type { Plugin } from 'vite'

// 1. 定义配置类型
interface BuildTimerOptions extends BasePluginOptions {
	/** 是否在构建完成后输出详细耗时分布 */
	detailed?: boolean
	/** 日志输出格式 */
	format?: 'simple' | 'table'
}

// 2. 实现插件类
class BuildTimerPlugin extends BasePlugin<BuildTimerOptions> {
	private startTime = 0
	private phaseTimes: Record<string, number> = {}

	protected getPluginName(): string {
		return 'build-timer'
	}

	protected getDefaultOptions(): Partial<BuildTimerOptions> {
		return {
			detailed: false,
			format: 'simple'
		}
	}

	protected validateOptions(): void {
		this.validator
			.field('detailed')
			.boolean()
			.field('format')
			.custom(val => !val || ['simple', 'table'].includes(val), 'format 必须是 simple 或 table')
			.validate()
	}

	protected addPluginHooks(plugin: Plugin): void {
		plugin.buildStart = () => {
			this.startTime = Date.now()
			this.phaseTimes = {}
		}

		plugin.writeBundle = () => {
			this.phaseTimes['write'] = Date.now()
		}

		plugin.closeBundle = () => {
			const totalTime = Date.now() - this.startTime
			this.logger.success(`构建完成,总耗时: ${totalTime}ms`)

			if (this.options.detailed) {
				for (const [phase, time] of Object.entries(this.phaseTimes)) {
					this.logger.info(`  ${phase}: ${time}ms`)
				}
			}
		}
	}
}

// 3. 导出工厂函数
export const buildTimer = createPluginFactory(BuildTimerPlugin)
export type { BuildTimerOptions }

使用自定义插件:

import { buildTimer } from './plugins/build-timer'

export default defineConfig({
	plugins: [buildTimer({ detailed: true, format: 'table' })]
})

五、通用工具模块

@meng-xi/vite-plugin/common 导出了一系列实用的工具函数,不仅框架内部使用,也可在业务代码中直接使用。

5.1 format — 格式化工具

import { padNumber, generateRandomHash, formatDate, parseTemplate, toCamelCase, toPascalCase, stripJsonComments } from '@meng-xi/vite-plugin/common'
函数说明示例
padNumber(num, length)数字补零padNumber(5, 2)'05'
generateRandomHash(length)生成随机哈希generateRandomHash(8)'a1b2c3d4'
formatDate(date, format)日期格式化formatDate(new Date(), '{YYYY}-{MM}-{DD}')'2026-05-20'
parseTemplate(template, values)模板字符串替换parseTemplate('{name}-{ver}', { name: 'app', ver: '1.0' })'app-1.0'
toCamelCase(str)转 camelCasetoCamelCase('pages/user/profile')'pagesUserProfile'
toPascalCase(str)转 PascalCasetoPascalCase('user-profile')'UserProfile'
stripJsonComments(str)移除 JSON 注释stripJsonComments('{// comment\n"a":1}')'{"a":1}'
formatDate 占位符

{YYYY}{YY}{MM}{DD}{HH}{mm}{ss}{SSS}{timestamp}

5.2 fs — 文件系统工具

import { checkSourceExists, ensureTargetDir, readDirRecursive, shouldUpdateFile, fileExists, runWithConcurrency, copySourceToTarget, writeFileContent, readFileContent } from '@meng-xi/vite-plugin/common'
函数说明
checkSourceExists(path)检查源路径是否存在,不存在则抛出详细错误
ensureTargetDir(path)确保目标目录存在,递归创建
readDirRecursive(path, recursive)递归读取目录,返回文件/目录条目列表
shouldUpdateFile(src, dest)比较修改时间和大小,判断是否需要更新
fileExists(path)异步检查文件是否存在
runWithConcurrency(items, handler, limit)带并发限制的批量执行
copySourceToTarget(src, dest, options)完整的文件复制实现,支持增量/并行
writeFileContent(path, content)写入文件,带权限错误提示
readFileContent(path)读取文件,带权限错误提示
CopyOptions 接口
interface CopyOptions {
	recursive: boolean // 是否递归复制
	overwrite: boolean // 是否覆盖
	incremental?: boolean // 是否增量
	parallelLimit?: number // 并发限制,默认 10
	skipEmptyDirs?: boolean // 是否跳过空目录
}
CopyResult 接口
interface CopyResult {
	copiedFiles: number // 复制的文件数
	skippedFiles: number // 跳过的文件数
	copiedDirs: number // 复制的目录数
	executionTime: number // 耗时(毫秒)
}

5.3 object — 对象工具

import { deepMerge } from '@meng-xi/vite-plugin/common'
deepMerge

深度合并多个对象,是框架配置合并的核心:

// 基本合并
deepMerge({ a: 1 }, { b: 2 }) // { a: 1, b: 2 }

// undefined 不覆盖已有值
deepMerge({ a: 1 }, { a: undefined }) // { a: 1 }

// null 会覆盖
deepMerge({ a: 1 }, { a: null }) // { a: null }

// 嵌套对象递归合并
deepMerge({ a: { b: 1 } }, { a: { c: 2 } }) // { a: { b: 1, c: 2 } }

// 数组直接覆盖(不合并)
deepMerge({ a: [1, 2] }, { a: [3, 4] }) // { a: [3, 4] }

5.4 validation — 参数验证器

import { Validator } from '@meng-xi/vite-plugin/common'

流畅的链式 API,用于验证插件配置:

const validator = new Validator(options)

validator
	.field('sourceDir')
	.required()
	.string()
	.custom(val => val.trim() !== '', '不能为空')
	.field('targetDir')
	.required()
	.string()
	.field('overwrite')
	.boolean()
	.default(true)
	.field('width')
	.number()
	.custom(val => val > 0, '必须大于 0')
	.field('items')
	.array()
	.field('config')
	.object()
	.validate() // 验证失败抛出 Error,成功返回 options
方法说明
.field(name)指定要验证的字段
.required()标记为必填
.string()验证字符串类型
.number()验证数字类型
.boolean()验证布尔类型
.array()验证数组类型
.object()验证对象类型
.default(value)设置默认值(仅 undefined/null 时生效)
.custom(fn, msg)自定义验证函数
.validate()执行验证,失败抛出错误

六、日志系统

@meng-xi/vite-plugin/logger 提供单例模式的日志管理器。

Logger 类

import { Logger } from '@meng-xi/vite-plugin/logger'
核心特性
  • 单例模式 — 全局唯一实例,统一管理所有插件日志
  • 插件级开关 — 每个插件可独立控制日志开关
  • 彩色输出 — 使用 ANSI 颜色码区分日志级别
  • 自动注销 — 插件销毁时自动清理日志配置
日志级别
级别图标颜色方法
success绿色logger.success(msg, data?)
infoℹ️青色logger.info(msg, data?)
warn⚠️黄色logger.warn(msg, data?)
error红色logger.error(msg, data?)
输出格式
✅ [@meng-xi/vite-plugin:build-progress] 构建完成
ℹ️ [@meng-xi/vite-plugin:copy-file] 复制文件成功:从 public 到 dist
⚠️ [@meng-xi/vite-plugin:generate-router] pages.json 中没有有效的页面配置
❌ [@meng-xi/vite-plugin:inject-ico] 未找到 </head> 标签
PluginLogger 接口

每个插件通过 PluginLogger 代理对象输出日志,由 BasePlugin 自动创建:

interface PluginLogger {
	success(message: string, data?: any): void
	info(message: string, data?: any): void
	warn(message: string, data?: any): void
	error(message: string, data?: any): void
}

七、子路径导出

@meng-xi/vite-plugin 支持精细化的子路径导出,便于按需引入:

路径内容典型场景
@meng-xi/vite-plugin全部导出日常使用
@meng-xi/vite-plugin/plugins仅插件只用插件不需要框架
@meng-xi/vite-plugin/common仅工具函数只用工具不用插件
@meng-xi/vite-plugin/factory仅框架开发自定义插件
@meng-xi/vite-plugin/logger仅日志自定义日志管理

每个子路径均提供 CJS、ESM 和类型定义三种格式:

{
	"./common": {
		"require": "./dist/common/index.cjs",
		"import": "./dist/common/index.mjs",
		"types": "./dist/common/index.d.ts"
	}
}

八、最佳实践

1. 插件顺序

buildProgress 不依赖顺序,可放在 plugins 数组任意位置。其他插件建议按以下顺序:

plugins: [
	buildProgress(), // 进度条(最先注册,最早触发)
	injectIco(), // 图标注入(transformIndexHtml 钩子)
	generateVersion(), // 版本生成(config + writeBundle 钩子)
	copyFile(), // 文件复制(writeBundle 钩子,enforce: 'post')
	generateRouter() // 路由生成(configResolved 钩子)
]

2. 条件启用

根据平台和环境变量控制插件启用:

const isH5 = process.env.UNI_PLATFORM === 'h5'
const isProd = viteEnv.VITE_USER_NODE_ENV === 'production'

plugins: [buildProgress({ enabled: !process.env.CI }), injectIco({ enabled: isH5 && isProd }), copyFile({ enabled: isH5 && isProd }), generateVersion({ enabled: isProd })]

3. 错误策略选择

场景推荐策略
开发环境throw(默认),快速暴露问题
CI/CDthrow,确保构建失败可见
非关键插件log,记录但不中断
可选功能ignore,静默跳过

4. 版本号在代码中的使用

// vite.config.ts
generateVersion({
	outputType: 'both',
	defineName: '__APP_VERSION__'
})

// src/utils/version.ts
declare const __APP_VERSION__: string

export function getVersion(): string {
	return __APP_VERSION__
}

// 用于错误上报
reportError({ version: __APP_VERSION__, ...errorInfo })

5. 路由配置的增量修改

开启 preserveRouteChanges 后,手动修改的路由 meta 不会被覆盖:

generateRouter({
	preserveRouteChanges: true,
	metaMapping: {
		navigationBarTitleText: 'title',
		requireAuth: 'requireAuth'
	}
})

首次生成后,手动添加 requireAuth: true

{ path: '/pages/admin/dashboard', name: 'pagesAdminDashboard', meta: { title: '管理后台', requireAuth: true } }

下次 pages.json 变化重新生成时,requireAuth: true 会被保留。

6. 自定义插件中复用工具函数

import { Validator, deepMerge, writeFileContent, readFileContent } from '@meng-xi/vite-plugin/common'

class MyPlugin extends BasePlugin<MyOptions> {
	protected validateOptions(): void {
		this.validator.field('inputDir').required().string().field('outputDir').required().string().validate()
	}

	protected async processData(): Promise<void> {
		const content = await readFileContent(this.options.inputDir)
		// ... 处理逻辑
		await writeFileContent(this.options.outputDir, result)
	}
}

九、常见问题解答

Q1:插件不生效?

排查步骤:

  1. 确认 enabled 未设为 false
  2. 确认 verbosetrue,查看日志输出
  3. 确认插件在 plugins 数组中正确注册
  4. 检查 errorStrategy,如果是 ignore 可能静默跳过了错误

Q2:buildProgress 在 CI 中显示乱码?

CI 环境通常是非 TTY,插件会自动降级为日志输出。如果仍有问题:

buildProgress({
	enabled: process.env.CI !== 'true' // CI 环境完全禁用
})

Q3:copyFile 增量复制不生效?

增量复制通过比较文件修改时间判断。如果源文件时间戳未变化但内容变了(如 git checkout),需要先触发文件修改时间更新。

Q4:generateVersion 的 define 注入如何在 TypeScript 中使用?

vite-env.d.ts 中声明类型:

declare const __APP_VERSION__: string
declare const __APP_VERSION___INFO: {
	version: string
	buildTime: string
	timestamp: number
	format: string
	[key: string]: unknown
}

Q5:generateRouter 支持非 uni-app 项目吗?

当前版本专为 uni-app 的 pages.json 格式设计。非 uni-app 项目可通过自定义插件实现类似功能,使用 @meng-xi/vite-plugin/factory 中的 BasePlugin 作为基类。

Q6:如何访问插件的内部状态?

所有插件返回的对象包含 pluginInstance 属性:

import type { PluginWithInstance } from '@meng-xi/vite-plugin/factory'
import type { BuildProgressOptions } from '@meng-xi/vite-plugin/plugins'

const progress = buildProgress() as PluginWithInstance<BuildProgressOptions>
console.log(progress.pluginInstance?.options)

Q7:多个插件的日志可以分别控制吗?

可以。每个插件的 verbose 选项独立控制日志开关:

;(buildProgress({ verbose: true }),
	copyFile({ verbose: false }), // 不输出日志
	generateVersion({ verbose: true }))

Q8:injectIco 仅 H5 平台有效?

是的。小程序和 App 平台不支持 HTML <link> 标签,建议条件启用:

injectIco({ enabled: process.env.UNI_PLATFORM === 'h5' })

十、API 速查表

插件

导出类型说明
buildProgressPluginFactory<BuildProgressOptions>构建进度条
copyFilePluginFactory<CopyFileOptions>文件复制
generateVersionPluginFactory<GenerateVersionOptions>版本号生成
generateRouterPluginFactory<GenerateRouterOptions>路由配置生成
injectIcoPluginFactory<InjectIcoOptions, string | InjectIcoOptions>图标注入

框架

导出类型说明
BasePluginabstract class插件抽象基类
createPluginFactoryfunction插件工厂函数创建器
BasePluginOptionsinterface基础插件配置
PluginWithInstanceinterface带实例引用的 Plugin 类型
PluginFactorytype工厂函数类型
OptionsNormalizertype选项标准化器类型

工具函数

导出说明
padNumber数字补零
generateRandomHash随机哈希生成
formatDate日期格式化
getDateFormatParams获取日期参数对象
parseTemplate模板字符串替换
toCamelCase转 camelCase
toPascalCase转 PascalCase
stripJsonComments移除 JSON 注释
deepMerge深度合并对象
Validator参数验证器类
checkSourceExists检查源路径存在
ensureTargetDir确保目标目录
readDirRecursive递归读取目录
shouldUpdateFile判断文件是否需更新
fileExists异步文件存在检查
runWithConcurrency带并发限制批量执行
copySourceToTarget文件复制实现
writeFileContent写入文件
readFileContent读取文件

日志

导出说明
Logger日志管理器类(单例)
PluginLogger插件日志代理接口

本文基于 @meng-xi/vite-plugin@0.0.7 版本撰写,如有更新请以最新文档为准。

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐