前言
在实际的移动端开发中,我们经常面临这些痛点:
- 多个 H5 项目,各自为战 — 每个项目独立一套配置,Lint、TypeScript、Vite 各玩各的
- UI 框架选型难 — NutUI、Vant、Varlet 各有优势,不同业务场景想用不同 UI
- Mock 接口重复写 — 每个项目写一套 Mock,费时费力
- 新建项目成本高 — 每次复制粘贴、改配置、接路由,至少半天
Vue H5 Template 就是为解决这些问题而生的。它是一个基于 Turborepo + Vue 3 + TypeScript 的移动端 Monorepo 模板,提供三套 UI 框架版本,共享一切可以共享的东西。
技术栈一览
| 技术 | 版本 | 说明 |
|---|---|---|
| Vue | 3.5 | Composition API + <script setup> |
| TypeScript | 6.0 | 全量覆盖,严格模式 |
| Vite | 8.0 | 构建工具,共享配置 |
| Turborepo | 2.9 | Monorepo 管理 + 缓存加速 |
| pnpm | 10.27 | 包管理器,workspace + catalog 协议 |
| Pinia | 3.0 | 状态管理 + 持久化 + AES 加密 |
| Vue Router | 5.0 | 路由管理 + NProgress 进度条 |
| Vue I18n | 11.3 | 国际化(简/繁/英/日/港) |
| Nitro | 2.x | Mock 后端服务 |
| NutUI / Vant / Varlet | 三套并存 | 三套移动端 UI 框架 |
项目结构
vue-h5-template/
├── apps/ # 📱 应用目录
│ ├── h5-nutui/ # NutUI 版 H5(端口 5777)
│ ├── h5-vant/ # Vant 版 H5(端口 5778)
│ ├── h5-varlet/ # Varlet 版 H5(端口 5779)
│ └── backend-mock/ # Nitro Mock 后端(端口 5320)
├── packages/ # 📦 共享包
│ ├── @core/ # 核心包(设计系统、composables、偏好设置)
│ ├── stores/ # Pinia 状态管理
│ ├── styles/ # 全局样式 + 各 UI 主题
│ ├── locales/ # 国际化语言包
│ └── utils/ # 工具函数(含 NProgress)
├── internal/ # 🔧 内部配置
│ ├── vite-config/ # 共享 Vite 配置工厂
│ ├── tsconfig/ # 共享 TypeScript 配置
│ └── lint-configs/ # ESLint/Prettier/Stylelint/Commitlint
├── scripts/ # 🛠️ CLI 工具
│ ├── vsh/ # 项目 CLI(lint、创建应用等)
│ └── turbo-run/ # 交互式选择运行
└── docs/ # 📖 多语言文档站(VitePress)
核心亮点
1. 三套 UI 框架,统一架构
项目同时支持 NutUI(京东风格)、Vant(有赞风格)、Varlet(Material Design)三套移动端 UI 框架:
apps/
├── h5-nutui/ → NutUI 4.3,适合电商类场景
├── h5-vant/ → Vant 4.9,适合通用 H5
└── h5-varlet/ → Varlet 3.12,适合 Material 风格
每个应用独立运行,共享路由结构、API 层、状态管理和国际化方案。切换 UI 框架只是换个 app 目录,核心逻辑一行不改。
三个 app 均按需自动导入,不需要手写 import:
// vite.config.ts 只需声明 UI 库类型
export default defineConfig(async () => ({
application: { uiLibrary: "vant" }, // 'nut' | 'vant' | 'varlet'
vite: {
/* 自定义配置 */
},
}));
剩下的 Resolver、auto-import、组件注册,全部由 @vh5/vite-config 自动处理。
2. 一键创建新应用
内置 create-app CLI,一行命令创建新 H5 应用:
pnpm create-app
交互式选择 UI 框架和应用名,自动生成:
- 完整的项目结构(路由、视图、API、状态管理)
- Vite 配置(含 Mock 代理和路径别名)
- TypeScript 配置(继承共享 tsconfig)
- 国际化支持(接入
@vh5/locales) - 共享样式引入
不需要复制粘贴,不需要手改配置,60 秒启动新应用。
3. Turborepo 加持的构建缓存
# 交互式选择启动
pnpm dev
# 直接启动指定应用
pnpm dev:vant
pnpm dev:nutui
pnpm dev:varlet
Turborepo 会自动:
- 缓存构建产物 — 代码没变就不重新构建,直接复用
- 并行执行 — 共享包与应用同时编译
- 依赖拓扑排序 — 自动处理包间依赖顺序,不用手动
--filter
增量构建从冷启动的 30s+ 降到缓存命中后的 2s 以内。
4. 内置 Nitro Mock 服务
不需要额外启动 Mock 服务,pnpm dev 时 Vite 自动拉起 Nitro Mock:
POST http://localhost:5320/api/auth/login # 登录(返回 JWT)
POST http://localhost:5320/api/auth/logout # 登出
GET http://localhost:5320/api/user/info # 用户信息
GET http://localhost:5320/api/product/list # 商品列表(支持分页)
GET http://localhost:5320/api/product/detail # 商品详情
支持 JWT 认证、请求拦截、分页查询,内置两个测试账号:
| 用户名 | 密码 | 角色 |
|---|---|---|
| user | 123456 | 普通用户 |
| admin | 123456 | 管理员 |
前端通过 Vite proxy 透明代理,开发体验和联调阶段完全一致,不改一行代码切到真实后端。
5. pnpm catalog 统一依赖版本
# pnpm-workspace.yaml
catalog:
vue: ^3.5.32
vite: ^8.0.8
typescript: ^6.0.2
vant: ^4.9.21
# ...
所有 package.json 里只写 "vant": "catalog:",版本全部集中在 catalog 管理。三个 app 用的同一个版本,升级只改一处,彻底解决版本漂移问题。
6. 状态管理:Pinia + 持久化 + AES 加密
import { initStores } from "@vh5/stores";
// 初始化时传入命名空间,多应用同域部署不冲突
await initStores(app, { namespace: "h5-vant-1.0.0-prod" });
- 开发环境:直接用
localStorage,方便 DevTools 调试 - 生产环境:
SecureLS+ AES 加密,敏感数据不裸奔 - 命名空间隔离:
h5-vant-xxx和h5-nutui-xxx的 key 不会互相污染
7. 国际化:四语言 + 动态加载
内置简体中文、繁体中文(台湾/香港)、英文、日文五个语言:
packages/locales/src/langs/
├── zh-CN/ # 简体中文
├── zh-TW/ # 繁体中文(台湾)
├── en-US/ # 英文
└── ja-JP/ # 日文
语言包放在共享包里,各 app 通过 @vh5/locales 按需动态加载,不增加首屏包体积:
import { loadLocaleMessages } from "@vh5/locales";
// 切换语言时才加载对应语言包
await loadLocaleMessages("en-US");
8. 路由进度条 + 动态标题
三个 app 均集成了 NProgress 路由进度条和自动标题更新:
// router/guard.ts
import { startProgress, stopProgress } from "@vh5/utils";
router.beforeEach(() => startProgress());
router.afterEach(() => stopProgress());
动态标题在 bootstrap 里通过 VueUse 的 useTitle 绑定路由 meta,路由切换自动更新 document.title,无需每个页面单独处理。
工程化配置
统一 Lint 规则
所有 ESLint / Prettier / Stylelint / Commitlint / OXLint 配置在 internal/lint-configs/ 集中管理,各 app 只需一行继承:
# 检查 + 自动修复
pnpm lint
# 格式化
pnpm format
Git commit 使用 Conventional Commits 规范,Lefthook 自动执行 pre-commit 检查。
共享 Vite 配置
@vh5/vite-config 提供 defineConfig 工厂函数,内置以下插件:
| 插件 | 说明 |
|---|---|
@vitejs/plugin-vue | Vue 3 SFC + defineModel |
unplugin-auto-import | API 自动导入(vue、pinia、vueuse) |
unplugin-vue-components | 组件按需自动注册 |
vite-plugin-vue-devtools | Vue DevTools |
postcss-px-to-viewport | px → viewport 移动端适配 |
vite-plugin-html | HTML 模板变量注入 |
vite-plugin-compression | Gzip/Brotli 构建压缩 |
vite-plugin-pwa | PWA 离线支持 |
nitro-mock | 自动启动 Mock 服务 |
vite:license | 构建产物注入版权信息 |
vsh CLI 工具集
pnpm create-app # 创建新 H5 应用
vsh lint # 代码检查
vsh check-circular # 循环依赖检测
vsh check-dep # 未使用依赖检查
vsh publint # package.json 规范检查
vsh code-workspace # 生成 VSCode workspace 文件
快速开始
# 克隆
git clone https://github.com/fonghehe/vue-h5-template.git
cd vue-h5-template
# 安装(需要 Node.js >= 20.12.0 + pnpm >= 10)
pnpm install
# 开发(交互式选择应用)
pnpm dev
# 或直接启动指定应用
pnpm dev:vant # Vant 版,端口 5778
pnpm dev:nutui # NutUI 版,端口 5777
pnpm dev:varlet # Varlet 版,端口 5779
# 创建新应用
pnpm create-app
# 构建所有应用
pnpm build
适合哪些场景
- ✅ 团队需要维护多个移动端 H5 项目
- ✅ 想在不同 UI 框架之间灵活切换
- ✅ 需要快速搭建标准化的新 H5 应用
- ✅ 希望统一团队的工程化规范(Lint、TypeScript、构建)
- ✅ 学习 Turborepo Monorepo 最佳实践
浏览器支持
支持现代浏览器和移动端浏览器,不支持 IE。
| Edge | Firefox | Chrome | Safari |
|---|---|---|---|
| ≥ 80 | ≥ 78 | ≥ 80 | ≥ 14 |
写在最后
这个模板目前在我自己的几个项目里实际使用,持续迭代中。
如果你觉得有帮助,欢迎 Star ⭐ 和 PR 🎉
有问题或建议欢迎提 Issue 讨论!