版本:0.1.6 | 协议:MIT | 依赖:Vite >=5.0.0 <8.0.0
写在前面
v0.1.6 的主题是:让自动导入更智能,让路由导航更安全,让工具层更实用。
v0.1.5 引入的 autoImport 插件需要逐一列举要导入的 API 名称------vue: ['ref', 'reactive', 'computed', ...],列表一长就容易遗漏或多余。v0.1.6 带来的通配符 '*'
支持,让你一行配置就能导入模块的全部命名导出。同时,generateRouter 新增了路由类型声明生成,为 @meng-xi/uni-router 扩展 RouteNameMap
接口,实现类型安全的路由导航。此外,Common 工具模块新增了 5 个通用函数,插件代码也完成了规范化重构。
本版重点:
| 能力 | 一句话说明 | 你需要做什么 |
|---|---|---|
autoImport 通配符导入 |
vue: ['*'] 自动导入模块所有命名导出 |
更新配置 |
autoImport Vue SFC 注入 |
import 语句注入到 <script setup> 块内部 |
无需操作 |
generateRouter 类型声明 |
生成 router.d.ts,扩展 RouteNameMap 接口 |
新增配置 |
| Common 工具模块增强 | 新增 parseTemplate、formatDate、writeFileSyncSafely 等 | 按需导入 |
| 插件代码规范化重构 | 各插件非核心逻辑提取到 common/ 子目录 |
无需操作 |
升级方式 :修改 devDependencies 中版本号为 ^0.1.6。无 Breaking Changes,完全向后兼容。
一、5 分钟快速上手
1.1 安装与最小配置
json
{
"devDependencies": {
"@meng-xi/vite-plugin": "^0.1.6"
}
}
typescript
import { autoImport, generateRouter } from '@meng-xi/vite-plugin'
export default defineConfig({
plugins: [
autoImport({
imports: { vue: ['*'] },
dts: true,
vueTemplate: true
}),
generateRouter({ dts: true })
]
})
1.2 立刻看到效果
之前:逐一列举要导入的 API
typescript
autoImport({
imports: {
vue: ['ref', 'reactive', 'computed', 'watch', 'watchEffect', 'onMounted', 'onUnmounted', 'nextTick', 'toRef', 'toRefs', ...]
}
})
之后:一行搞定
typescript
autoImport({
imports: { vue: ['*'] }
})
插件会自动从 vue 的 .d.ts 类型声明文件中提取所有命名导出,无需手动维护列表。
1.3 路由类型安全
之前:路由名称是普通字符串,拼错不会报错
typescript
uni.navigateTo({ name: 'pagesIndexIndx' }) // 拼错了,运行时才发现
之后 :启用 dts: true 后,路由名称有类型检查
typescript
uni.navigateTo({ name: 'pagesIndexIndx' }) // TS 报错:类型 '"pagesIndexIndx"' 不能分配给类型 '"pagesIndexIndex" | ...'
二、核心能力一:autoImport 通配符导入
2.1 通配符解析策略
当 imports 配置中使用 '*' 时,插件会自动解析模块的所有命名导出:
imports: { vue: ['*'] }
↓
1. 优先从 .d.ts 类型声明文件解析(最准确)
↓ 失败
2. 尝试作为本地文件路径解析
↓ 失败
3. 尝试从 node_modules 解析运行时入口
↓ 失败
4. 返回空数组
为什么优先使用 .d.ts? bundler 格式的运行时入口文件(如 vue.runtime.esm-bundler.js)通常只包含 export { compile } 等极少导出,而完整的 API 通过动态方式导出,静态正则无法匹配。.d.ts
文件包含完整的静态类型声明,能准确反映模块的所有导出。
2.2 使用方式
typescript
// 简写格式
autoImport({
imports: {
vue: ['*'], // 自动导入 vue 的所有命名导出
'vue-router': ['*'], // 自动导入 vue-router 的所有命名导出
pinia: ['defineStore', 'storeToRefs'] // 也可以混合使用
}
})
// 完整格式
autoImport({
imports: [
{ module: 'vue', names: ['*'] },
{ module: 'lodash', names: ['debounce'], defaultImport: false }
]
})
2.3 Vue SFC 注入
v0.1.6 修复了 autoImport 与 uni-app 插件的协同问题。此前 transform 钩子使用 enforce: 'post',导致裸模块标识符无法被 Vite 正确解析。现在改回 enforce: 'pre',并新增 injectIntoScriptSetup
函数,将 import 语句注入到 <script setup> 块内部:
vue
<!-- 处理前 -->
<script setup lang="ts">
const count = ref(0)
const double = computed(() => count.value * 2)
</script>
<!-- 处理后 -->
<script setup lang="ts">
import { ref, computed } from 'vue'
const count = ref(0)
const double = computed(() => count.value * 2)
</script>
2.4 修复列表
| 问题 | 原因 | 修复 |
|---|---|---|
vue: ['*'] 只解析出 compile |
resolveWildcardExports 走了运行时入口 |
优先从 .d.ts 解析 |
node_modules 文件被错误处理 |
默认 fileFilter 未排除 node_modules |
正则改为 ^(?!.*node_modules) |
| 裸模块标识符无法解析 | enforce: 'post' 时 Vite 已完成模块解析 |
改回 enforce: 'pre' |
makeCallback 语法错误 |
匿名函数作为函数声明调用 | 改用 IIFE 形式 |
2.5 配置选项变更
| 选项 | 变更前默认值 | 变更后默认值 | 说明 |
|---|---|---|---|
| imports | - | - | 新增支持 '*' 通配符格式 |
| fileFilter | `/.(vue | jsx | tsx |
三、核心能力二:generateRouter 路由类型声明
3.1 类型声明生成
新增 dts 选项,为 @meng-xi/uni-router 模块扩展 RouteNameMap 接口:
typescript
generateRouter({ dts: true })
生成的 src/router.d.ts:
typescript
import '@meng-xi/uni-router'
declare module '@meng-xi/uni-router' {
interface RouteNameMap {
/** 首页 */
pagesIndexIndex: { path: '/pages/index/index'; meta: { title: string; isTab: true } }
/** 个人中心 */
pagesUserProfile: { path: '/pages/user/profile'; meta: { title: string; requireAuth: true } }
}
}
3.2 dts 选项
| 值 | 行为 |
|---|---|
false |
不生成类型声明文件(默认) |
true |
使用默认路径 src/router.d.ts |
string |
在指定路径生成类型声明文件 |
3.3 类型声明特性
- TSDoc 注释:每条路由自动生成页面标题注释
- 完整元信息映射 :
meta中的字符串字段类型为string,布尔true字段类型为字面量true - 增量写入:仅在内容发生变化时才写入文件,减少不必要的文件 IO
四、Common 工具模块增强
v0.1.6 为 Common 工具模块新增了 5 个通用函数:
4.1 common/format
parseTemplate --- 替换模板字符串中的 {``{key}} 占位符:
typescript
import { parseTemplate } from '@meng-xi/vite-plugin/common/format'
parseTemplate('Hello {{name}}!', { name: 'World' })
// 'Hello World!'
parseTemplate('{{YYYY}}-{{MM}}-{{DD}}', getDateFormatParams())
// '2026-06-07'
键名中的正则特殊字符会被自动转义,值中的 $ 也会被安全处理。
formatDate --- 使用 {YYYY}、{MM} 等占位符格式化日期字符串:
typescript
import { formatDate } from '@meng-xi/vite-plugin/common/format'
formatDate(new Date(), '{YYYY}-{MM}-{DD}T{HH}:{mm}:{ss}')
// '2026-06-07T15:30:00'
4.2 common/fs
writeFileSyncSafely --- 同步写入文件,自动创建不存在的目录:
typescript
import { writeFileSyncSafely } from '@meng-xi/vite-plugin/common/fs'
// 目录不存在时自动递归创建,适用于 transform 等同步钩子
writeFileSyncSafely('/project/src/auto-imports.d.ts', 'declare global { ... }')
shouldUpdateFileContent --- 对比文件内容是否需要更新:
typescript
import { shouldUpdateFileContent } from '@meng-xi/vite-plugin/common/fs'
if (shouldUpdateFileContent('/project/src/router.d.ts', newContent)) {
writeFileSyncSafely('/project/src/router.d.ts', newContent)
}
4.3 common/html
escapeHtmlAttr --- 转义 HTML 属性值中的特殊字符:
typescript
import { escapeHtmlAttr } from '@meng-xi/vite-plugin/common/html'
escapeHtmlAttr('hello "world" & <friends>')
// 'hello "world" & <friends>'
转义 &、"、'、<、> 五种字符,防止属性注入攻击。
五、插件代码规范化重构
按照 autoImport/common 目录规范,将各插件中不属于插件核心逻辑的函数、常量等提取到 common/ 子目录,通过 common/index.ts 聚合导出:
| 插件 | 提取内容 |
|---|---|
buildProgress/common |
常量和工具函数 |
generateRouter/common |
路由工具函数和类型声明生成逻辑(dts.ts) |
envGuard/common |
运行时守卫、模板生成、校验逻辑 |
faviconManager/common |
类型定义 |
htmlInject/common |
代码生成器和校验器 |
loadingManager/common |
常量、函数体生成器、代码生成器和校验器 |
versionUpdateChecker/common |
代码生成器和校验器 |
重构原则 :插件主文件只保留生命周期钩子和核心流程,工具函数和类型定义移入 common/,保持代码结构清晰、职责单一。
六、实战场景
6.1 Vue 3 + uni-app 全家桶
typescript
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import { autoImport, generateRouter } from './uni_modules/vite-plugin/js_sdk/index.mjs'
export default defineConfig({
plugins: [
uni(),
autoImport({
imports: {
vue: ['*'],
'@dcloudio/uni-app': ['onLaunch', 'onShow', 'onHide', 'onLoad']
},
dts: true,
vueTemplate: true
}),
generateRouter({ dts: true })
]
})
6.2 纯 Vite 项目
typescript
import { defineConfig } from 'vite'
import { autoImport, buildProgress, envGuard } from '@meng-xi/vite-plugin'
export default defineConfig({
plugins: [
autoImport({
imports: {
vue: ['*'],
'vue-router': ['*'],
pinia: ['defineStore', 'storeToRefs']
},
dirs: ['src/composables'],
dts: 'src/auto-imports.d.ts',
vueTemplate: true
}),
buildProgress({ format: 'bar' }),
envGuard({
required: {
VITE_API_URL: { type: 'url', required: true }
}
})
]
})
6.3 使用 Common 工具函数构建自定义插件
typescript
import { writeFileSyncSafely, shouldUpdateFileContent } from '@meng-xi/vite-plugin/common/fs'
import { formatDate } from '@meng-xi/vite-plugin/common/format'
import { escapeHtmlAttr } from '@meng-xi/vite-plugin/common/html'
// 在 transform 钩子中同步写入类型声明文件
function generateAndWriteDts(filePath: string, content: string): void {
if (shouldUpdateFileContent(filePath, content)) {
writeFileSyncSafely(filePath, content)
}
}
// 格式化版本号
const version = formatDate(new Date(), '{YYYY}.{MM}.{DD}')
// 安全地注入 HTML 属性
const safeAttr = escapeHtmlAttr(userInput)
七、子路径导出变更
| 子路径 | 变更 | 内容 |
|---|---|---|
@meng-xi/vite-plugin/common/format |
新增导出 | parseTemplate、formatDate |
@meng-xi/vite-plugin/common/fs |
新增导出 | writeFileSyncSafely、shouldUpdateFileContent |
@meng-xi/vite-plugin/common/html |
新增导出 | escapeHtmlAttr |
八、迁移指南
从 v0.1.5 升级到 v0.1.6
1. 使用通配符简化配置(可选)
typescript
// 之前
autoImport({
imports: {
vue: ['ref', 'reactive', 'computed', 'watch', 'onMounted', 'onUnmounted', 'nextTick']
}
})
// 之后
autoImport({
imports: { vue: ['*'] }
})
2. 启用路由类型声明(可选)
typescript
generateRouter({ dts: true })
// 或自定义路径
generateRouter({ dts: 'src/types/router.d.ts' })
3. 使用新增的 Common 工具函数(可选)
typescript
import { parseTemplate, formatDate } from '@meng-xi/vite-plugin/common/format'
import { writeFileSyncSafely, shouldUpdateFileContent } from '@meng-xi/vite-plugin/common/fs'
import { escapeHtmlAttr } from '@meng-xi/vite-plugin/common/html'
本文基于 @meng-xi/vite-plugin@0.1.6 版本撰写,所有代码示例均来自实际源码。