前言
很多 uni-app 项目一开始都很快:建页面、调接口、跑 H5、发小程序,好像没有什么难度。
但当项目进入真实业务阶段,问题会迅速变多:登录态怎么持久化?不同角色如何控制页面权限?小程序主包体积如何控制?H5 扫码和微信小程序能力如何共存?UI 组件库、暗黑模式、Tailwind、多端样式又该怎么统一?
这个项目就是围绕这些真实问题整理出来的一个 uni-app-template:它不是空白脚手架,而是一个基于 uni-app + Vue 3 + Vite 的多端业务启动模板,内置了登录、权限、角色化 TabBar、Wot UI、Tailwind CSS、Mock、扫码、二维码、图表分包、微信小程序上传等常见能力。
项目地址:
https://github.com/jiayc4215/uniapp-template
技术栈
当前模板主要使用:
uni-app 3:负责多端应用框架能力Vue 3:组合式 API 开发业务页面Vite 5:提供开发和构建能力Pinia:管理登录态、用户信息、主题和 TabBar 状态Wot Design Uni:提供跨端 UI 组件Tailwind CSS 4 + weapp-tailwindcss:统一 H5 和小程序端原子类写法@uni-helper/unh:封装开发、构建与配置生成流程@uni-helper/vite-plugin-uni-pages:通过页面文件和definePage生成页面配置@uni-helper/vite-plugin-uni-manifest:以manifest.config.js管理应用配置better-mock:开发环境 Mock 登录与用户信息接口uni-echarts + echarts:提供图表能力jsQR:支持 H5 摄像头扫码解析二维码uni-mini-ci:支持微信小程序 CLI 上传
为什么不是一个空白模板
空白模板的优点是干净,但真实项目往往需要重复搭建很多基础设施。
这个模板更偏向“业务启动模板 + 多端能力示例”,已经提前处理了几个常见工程问题:
- 页面权限:页面通过
definePage({ rules: [...] })声明允许访问的角色 - 路由守卫:在跳转前统一校验登录态、白名单和角色权限
- 角色菜单:自定义 TabBar 根据当前角色动态展示
- 持久化状态:登录态和用户信息由 Pinia 统一维护
- 多端样式:Wot UI 与 Tailwind CSS 共同支撑业务页面
- 暗黑模式:结合 uni-app 主题变量、Wot UI ConfigProvider 和语义色
- 分包优化:图表、扫码、二维码等能力放入分包,降低主包压力
- 小程序上传:内置微信小程序构建和上传脚本,方便接入发布流程
项目结构设计
源码主要放在 src 目录:
src/
├── api/ # 接口定义
├── components/ # 公共业务组件
├── composables/ # 组合式函数
├── echarts-modules/ # 图表分包
├── mock/ # 本地 Mock
├── pages/ # 主包页面
├── public-modules/ # 公共能力分包,例如扫码、二维码
├── router/ # 路由拦截与权限控制
├── store/ # Pinia 状态管理
├── tabbar/ # 自定义 TabBar
├── utils/ # 请求、路由、环境等工具
├── App.vue
└── main.js
根目录里保留了几个关键配置文件:
manifest.config.js # uni-app manifest 配置源文件
pages.config.js # pages.json 配置源文件
unh.config.js # @uni-helper/unh 配置
vite.config.js # Vite 与 uni-app 插件配置
pages.json 和 manifest.json 不再手写维护,而是由 @uni-helper/unh 根据源配置、页面内 definePage 和 manifest.config.js 自动生成。这样做的好处是配置入口更集中,页面规则也更靠近页面本身。
登录、权限与角色化 TabBar
模板内置了两个角色:
adminuser
页面可以通过 definePage 声明访问规则:
<script setup>
definePage({
style: {
navigationBarTitleText: "管理台"
},
rules: ["admin"]
})
</script>
路由权限主要由三部分组成:
- 页面内
definePage声明页面规则 src/router/permission.js在路由跳转前校验登录态和角色src/tabbar/config.js根据角色生成自定义 TabBar
这套设计让权限配置比较直观:新增一个页面时,可以直接在页面文件里写清楚它属于哪个角色;新增一个角色时,也能沿着登录接口、页面规则、TabBar 配置这条链路逐项检查。
权限跳转规则也比较完整:
- 已登录访问登录页时,自动跳转首页
- 未登录访问非白名单页面时,跳转登录页并携带
redirect - 已登录访问带
rules的页面时,校验用户角色 - 权限不足时,跳转到错误页
UI 与样式:Wot UI + Tailwind CSS
项目集成了 Wot Design Uni,并通过 pages.config.js 的 easycom 自动解析 wd-* 组件。业务页面可以直接使用 Wot UI 组件,不需要在每个页面里重复导入。
同时,模板也接入了 Tailwind CSS 4 + weapp-tailwindcss,用于统一 H5 和小程序端的原子类写法。安装依赖后会执行:
weapp-tw patch
这一步用于适配小程序端 Tailwind 转换。
在暗黑模式上,项目没有简单堆 dark: 类,而是采用了更工程化的三层方案:
manifest.config.js开启 H5 和微信小程序的darkmodesrc/theme.json提供 uni-app 平台主题变量wd-config-provider接管 Wot UI 组件主题,并通过 Tailwind 语义色服务业务页面
例如业务页面优先使用语义类:
<view class="bg-fill-bottom text-text-main">
<view class="border border-line-main bg-fill-oppo">
<text class="text-text-secondary">内容</text>
</view>
</view>
这样页面不需要硬编码两套颜色,也更容易保持 H5 和小程序端视觉一致。
分包实践:把重能力放到该去的地方
小程序项目绕不开包体积问题。模板中把图表和公共能力拆到了分包:
src/echarts-modules # 图表分包
src/public-modules # 扫码、二维码等公共能力分包
图表能力使用 uni-echarts + echarts,并推荐从 echarts/core 按需注册图表、组件和渲染器:
import { PieChart } from "echarts/charts"
import { DatasetComponent, LegendComponent, TooltipComponent } from "echarts/components"
import * as echarts from "echarts/core"
import { CanvasRenderer } from "echarts/renderers"
echarts.use([LegendComponent, TooltipComponent, DatasetComponent, PieChart, CanvasRenderer])
同时,微信小程序端开启了分包优化:
export default defineManifestConfig({
"mp-weixin": {
optimization: {
subPackages: true
}
}
})
并配合 @uni-ku/bundle-optimizer 控制跨包引用和构建表现。对于业务项目来说,这种拆分方式比后期再被动治理主包体积更稳。
H5 扫码与二维码能力
模板里还放了一个实践项目:即客二维码解码。它是一个二维码处理工具示例,支持二维码解析和生成。
其中 H5 扫码基于:
navigator.mediaDevices.getUserMediacanvasjsQR
摄像头画面会绘制到 canvas,再交给 jsQR 解析二维码内容。扫码组件识别成功后触发 success 事件,扫码页通过 uni.$emit("scanResult", data) 抛出结果。
需要注意的是,H5 摄像头能力对运行环境有要求:
- 页面需要运行在 HTTPS 环境
- iOS 浏览器以 Safari 内核权限表现为准
- 部分旧安卓浏览器可能不支持
getUserMedia - 离开页面时要释放
MediaStreamTrack
项目文档里也对常见错误做了整理,比如 NotAllowedError、NotFoundError、NotReadableError、SecurityError 等,方便排查摄像头授权问题。
Mock 与请求封装
开发环境下,如果设置:
VITE_APP_MOCK=true
src/main.js 会动态导入 src/mock,启用本地 Mock。
当前 Mock 主要覆盖:
- 登录接口
- 用户信息接口
- 不同角色返回不同 token 和用户信息
这对模板项目很有用。即使后端接口还没准备好,也可以先把登录、角色权限、TabBar 切换、页面跳转这些核心链路跑通。
微信小程序构建与上传
项目提供了微信小程序上传脚本:
pnpm upload:mp
也支持指定版本号、描述和机器人编号:
pnpm upload:mp --version=1.0.1
pnpm upload:mp --desc="修复登录问题"
pnpm upload:mp --version=1.0.1 --desc="版本说明" --robot=2
上传流程大致是:
- 构建微信小程序产物
- 读取生产环境变量中的
VITE_WX_APPID - 查找上传私钥
- 临时生成
.minicirc - 执行
minici --platform weixin - 上传结束后删除临时配置
私钥文件不会提交到仓库,上传前需要在微信公众平台开通“小程序代码上传”能力,并配置上传 IP 白名单。
快速开始
环境要求:
Node.js >= 20.19.0
pnpm
安装依赖:
pnpm install
启动 H5:
pnpm dev:h5
启动微信小程序:
pnpm dev:mp-weixin
生产构建:
pnpm build:h5
pnpm build:mp-weixin
代码检查:
pnpm lint
pnpm lint:fix
pnpm lint:prettier
文档站点位于 docs/ 目录,是一个独立的 VitePress 项目:
cd docs
pnpm install
pnpm docs:dev
适合哪些场景
这个模板适合:
- 快速启动 H5 或微信小程序业务项目
- 需要登录、权限、角色菜单的中后台或业务应用
- 希望统一 Wot UI、Tailwind CSS、多端样式的团队
- 需要扫码、二维码、图表、暗黑模式等常见能力示例的项目
- 想参考 uni-app 多端工程化配置的开发者
它不追求把所有业务都封装进去,而是把多数项目都会踩到的基础设施提前搭好。这样新项目开始时,不需要从登录、权限、分包、主题、构建发布这些问题上重新造轮子。
总结
uniapp-template 的核心价值,不是“能跑一个页面”,而是把一个 uni-app 多端项目从工程化、权限体系、UI 规范、分包策略、Mock 调试到小程序上传链路都串了起来。
如果你正在做 uni-app、Vue 3、小程序、H5 多端项目,这个模板可以作为启动项目,也可以作为工程配置参考。尤其是当项目需要角色权限、动态 TabBar、暗黑模式、扫码、图表分包和微信小程序上传时,它能省掉很多重复搭建成本。
文档地址:
https://jiayc4215.github.io/uniapp-template/