版本:1.4.0 | 协议:MIT | 依赖:Vite >=5.0.0 <9.0.0
写在前面
v1.4.0 的主题是:新增 defineUniPage 宏声明页面配置,并重构页面生成架构,统一监听与串行生成。
v1.3.0 通过 generateUni 将「扫描页面 → pages.json → 路由配置」收敛为一条流水线,但页面配置仍依赖 <route-config> 自定义块。v1.4.0 新增 defineUniPage 宏------在 <script setup>(或 <script> 顶层)中直接调用声明页面配置,功能与 <route-config> 一致、写法更贴近 JS/TS,且优先级更高。
同时,本版抽取公共 producePages() 流水线消除 generatePages / generateUni 的重复代码,新增 DirectoryWatcher / TaskQueue 公共模块统一三个生成插件的监听与串行生成,并增强 factory 的类型安全。
本版重点:
| 能力 | 一句话说明 | 你需要做什么 |
|---|---|---|
新增 defineUniPage 宏 |
在 <script setup> 中调用宏声明页面配置,优先级高于 <route-config> |
用宏替换 <route-config>(可选) |
| 宏类型声明自动生成 | 自动生成全局 dts,IDE 开箱识别宏(dts 可自定义或关闭) |
无需配置,自动生效 |
| 页面生成架构重构 | 抽取公共 producePages() 流水线,消除 generatePages / generateUni 重复代码 |
无感知,行为等价 |
| 公共模块新增 | DirectoryWatcher(目录递归监听)/ TaskQueue(串行任务队列) |
可直接按需导入使用 |
| 监听与串行化统一 | generatePages / generateUni / generateRouter 三者统一串行队列 + 目录监听 | 无需配置,自动生效 |
| factory 类型增强 | 新增 FunctionHookMap / getBaseDefaults(),钩子注册更类型安全 |
插件开发者无感,类型导出保持兼容 |
升级方式 :修改 devDependencies 中版本号为 ^1.4.0。无 Breaking Change,1.x 用户可平滑升级。
一、5 分钟快速上手
1.1 安装与升级
json
{
"devDependencies": {
"@meng-xi/vite-plugin": "^1.4.0"
}
}
1.2 用宏声明页面配置
vue
<!-- src/pages/mine/mine.vue -->
<script setup lang="ts">
defineUniPage({
title: '我的',
name: 'MinePage',
isTab: true,
tab: { text: '我的', order: 2 }
})
</script>
- 宏无需 import ,插件默认自动生成全局类型声明
src/define-uni-page.d.ts,IDE(Vue (Official) / Volar / tsc)直接识别,获得类型提示与编译期检查 - 同一页面同时声明宏与
<route-config>时,以宏为准(顶层字段按宏覆盖) - 宏在扫描时被消费,构建时自动移除调用,运行时不留痕
1.3 关闭或自定义宏类型声明
typescript
generatePages({
// 自定义输出路径
dts: 'types/define-uni-page.d.ts'
})
// 或关闭自动生成
generatePages({ dts: false })
generateUni 通过 pages.dts 配置,用法一致。
二、defineUniPage 宏详解
2.1 能力总览
| 能力 | 说明 |
|---|---|
| 优先级 | 高于 <route-config>:同时声明时顶层同名字段以宏为准 |
| 参数 | JS 对象字面量,支持注释、单引号、尾随逗号与嵌套对象(tab / style / meta) |
| 适用位置 | <script setup> 或 <script> 顶层 |
| 运行时无痕 | 扫描时消费 + transform 自动移除调用,无需 import、不会 ReferenceError |
| IDE 识别 | 自动生成全局声明(默认 src/define-uni-page.d.ts),Vue (Official) / Volar / tsc 开箱识别 |
2.2 与 <route-config> 的优先级
同一页面同时声明宏与自定义块时,顶层字段以宏为准:
vue
<script setup lang="ts">
defineUniPage({ title: '首页(宏优先)' })
</script>
<route-config lang="jsonc">
{
"title": "首页",
"isTab": true
}
</route-config>
最终 pages.json 中标题为宏的 '首页(宏优先)'。
2.3 <route-config> 增强:JSONC
<route-config> 自定义块解析同步支持 JSONC (注释 + 尾随逗号),与 lang="jsonc" 的 IDE 高亮语义一致:
vue
<route-config lang="jsonc">
{
// 支持注释与尾随逗号
"title": "首页",
"isTab": true
}
</route-config>
三、页面生成架构重构
3.1 抽取公共 producePages 流水线
新增 generatePages/helpers/produce.ts 的公共 producePages() 函数,将「扫描页面 + <route-config> / defineUniPage → 组装 → 合并」抽取为内存流水线:
generatePages直接写盘;generateUni内存直传阶段二,消除「先写盘再读盘」的往返- 删除
generateUni内部重复实现(约 76 行),统一复用generatePages公共逻辑
3.2 监听与串行化统一
generatePages/generateUni/generateRouter三者统一使用TaskQueue串行生成,避免高频变更时并发读改写竞态generatePages/generateUni统一使用DirectoryWatcher管理页面目录监听(此前为各自私有的fs.watch循环)generateRouter监听 pages.json 变更时同样走串行队列(此前直接 await 重新生成)
四、公共模块(新增)
4.1 DirectoryWatcher(common/fs)
目录递归监听器,统一管理多目录监听:
typescript
import { DirectoryWatcher } from '@meng-xi/vite-plugin/common/fs'
const watcher = new DirectoryWatcher({
dirs: ['/abs/pages', '/abs/pages-sub'],
onChange: () => regenerate(),
logger: { info: console.log, warn: console.warn },
label: '页面目录'
})
watcher.start() // 返回成功建立监听的目录数量
watcher.stop()
- 提供
start()/stop()/size - 平台不支持
recursive时自动降级跳过并告警,避免插件崩溃
4.2 TaskQueue(common/concurrency)
串行任务队列,将异步任务按提交顺序依次执行:
typescript
import { TaskQueue } from '@meng-xi/vite-plugin/common/concurrency'
const queue = new TaskQueue()
queue.run(() => generate()) // 第二个任务等待第一个完成后执行
queue.run(() => generate())
- 单个任务失败不阻塞后续任务
- 适用于高频触发(如文件监听)时避免并发读改写竞态
五、factory 增强
5.1 FunctionHookMap
新增 FunctionHookMap 类型:registerHook / registerOrderedHook 的钩子名泛型约束从 keyof Plugin 收紧为仅限函数型钩子,排除 name / enforce / apply 等非函数属性,提升钩子注册的编译期类型安全。
5.2 getBaseDefaults
新增可重写的 getBaseDefaults() 方法,将基础默认配置(enabled / verbose / errorStrategy)提取为子类可覆盖的独立方法,便于自定义插件调整基础默认值。
六、细节修复
- generatePages / generateUni 的
<route-config>虚拟模块请求匹配由id.includes('vue')收紧为id.includes('?vue'),避免误拦截 <route-config>解析支持 JSONC 尾随逗号,与lang="jsonc"的 IDE 高亮语义一致
七、插件清单(不变)
插件总数维持 17 个、7 个分组,本版无新增 / 删除插件,重点是能力增强与内部重构。
| 分组 | 插件 |
|---|---|
| generate | autoImport、generateUni、generatePages、generateRouter、generateVersion |
| analyze | buildProgress、bundleAnalyzer |
| compress | compressAssets、imageOptimizer |
| copy | assetManifest、copyFile |
| guard | envGuard |
| inject | faviconManager、htmlInject、loadingManager、versionUpdateChecker |
| proxy | proxyManager |
八、实战场景
8.1 uni-app 项目:宏 + 流水线
typescript
// vite.config.ts
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import { generateUni } from '@meng-xi/vite-plugin'
export default defineConfig({
plugins: [
uni(),
generateUni({
pagesJsonPath: 'src/pages.json',
pages: {
pagesDir: 'src/pages',
subPackages: [{ root: 'pages-sub', dir: 'src/pages-sub' }],
entryPage: 'pages/index/index',
dts: 'src/define-uni-page.d.ts', // defineUniPage 宏的全局类型声明
tabBar: { color: '#999999', selectedColor: '#42b883' }
},
router: {
outputPath: 'src/router.config.ts',
dts: 'src/router.d.ts'
}
})
]
})
页面内就近声明(宏优先):
vue
<!-- src/pages/index/index.vue -->
<script setup lang="ts">
defineUniPage({
title: '首页',
isTab: true,
tab: { order: 0 }
})
</script>
8.2 独立使用公共模块
typescript
// 串行化高频任务
import { TaskQueue } from '@meng-xi/vite-plugin/common/concurrency'
// 递归监听目录
import { DirectoryWatcher } from '@meng-xi/vite-plugin/common/fs'
九、注意事项
defineUniPage宏参数需为纯对象字面量(不支持变量 / 表达式),否则静默忽略- 宏在构建时被自动移除,无需 import ,但需保证 IDE 识别(
dts默认生成,或项目 tsconfig include 已生成的声明文件) - 同时声明宏与
<route-config>时以宏为准;若仅用<route-config>,建议添加lang="jsonc"获得 IDE 高亮 - 架构重构为内部实现,
generatePages/generateUni/generateRouter对外 API 与行为完全兼容 DirectoryWatcher/TaskQueue为新增公共导出,子路径导入即可使用,不影响原有 API
写在最后
v1.4.0 让页面配置声明从「模板块」升级为「宏调用」:defineUniPage 一个函数、一处调用、类型安全,且优先级天然高于 <route-config>。
- 宏能力让页面配置更贴近 JS/TS 开发习惯,配合自动生成的全局声明,IDE 体验与 Vue 官方宏一致
- 架构重构抽取公共流水线与公共模块,三个生成插件统一监听与串行生成,代码更精简、行为更一致
- 零破坏性升级让 1.x 用户可平滑迁移
后续版本将聚焦于:宏的更多配置来源(如 manifest.json)、uni-app 条件编译深度集成。如果你有任何建议或问题,欢迎在 GitHub Issues 反馈。