分包开发
当移动端页面越来越多,尤其是微信小程序体积接近限制时,需要把低频页面放到分包中。youlai-app 已经在路由插件里预留了分包目录,后续新增分包页面按本文操作即可。
什么时候需要分包?
| 场景 | 建议 |
|---|---|
| 首页、工作台、我的等高频入口 | 放主包 src/pages |
| 管理功能详情页、低频设置页 | 可放分包 src/subPages |
| 图表、富文本、文件预览等依赖较重页面 | 优先考虑分包 |
| 首屏必须立即访问的页面 | 不建议放分包 |
当前项目配置
分包扫描配置在 vite.config.ts:
ts
UniPages({
dts: "src/types/uni-pages.d.ts",
subPackages: ["src/subPages"],
exclude: ["**/components/**/*.*"],
})含义:
| 配置 | 说明 |
|---|---|
src/pages | 默认主包页面目录 |
src/subPages | 分包页面目录 |
exclude | 排除组件目录,避免组件被识别为页面 |
src/types/uni-pages.d.ts | 自动生成路由类型声明 |
src/pages.json 由 @uni-helper/vite-plugin-uni-pages 自动生成,不需要手动维护。
推荐目录结构
建议按业务域组织分包,避免把所有低频页面堆在一个目录里:
text
src/
├── pages/ # 主包:高频入口
│ ├── index/index.vue
│ ├── work/index.vue
│ └── mine/index.vue
└── subPages/ # 分包:低频或较重页面
├── system/
│ ├── user/detail.vue
│ └── role/detail.vue
├── report/
│ └── visit-trend.vue
└── settings/
└── advanced.vue生成后的分包路径通常是:
text
/subPages/system/user/detail
/subPages/report/visit-trend
/subPages/settings/advanced新增一个分包页面
例如新增用户详情页:
text
src/subPages/system/user/detail.vue页面中声明配置:
vue
<script setup lang="ts">
definePage({
name: "userDetail",
style: {
navigationBarTitleText: "用户详情",
},
meta: {
requireAuth: true,
},
})
</script>跳转时使用生成后的路径:
ts
uni.navigateTo({
url: `/subPages/system/user/detail?id=${id}`,
});如果使用 uni-mini-router:
ts
router.push({
path: "/subPages/system/user/detail",
query: { id },
});主包和分包怎么划分?
| 放主包 | 放分包 |
|---|---|
| TabBar 页面 | 详情页、编辑页、配置页 |
| 登录页 | 低频管理页 |
| 首页首屏依赖页面 | 图表、富文本、预览类重页面 |
| 必须秒开的页面 | 很少访问但代码较重的页面 |
原则:主包只保留“启动就可能访问”的页面,其他页面尽量按业务域拆分。
分包里的组件怎么放?
如果组件只服务某个分包,可以放在分包内部:
text
src/subPages/report/
├── components/
│ └── TrendCard.vue
└── visit-trend.vue项目配置了:
ts
exclude: ["**/components/**/*.*"]所以分包内部的 components 目录不会被误识别成页面。
如果组件会被主包和多个分包复用,放到公共目录:
text
src/components/
src/composables/
src/utils/分包与 layout
分包页面同样使用 definePage() 声明布局。
普通分包页面通常不用写 layout,默认使用 default:
ts
definePage({
name: "userDetail",
style: { navigationBarTitleText: "用户详情" },
})如果是完全自定义页面,可关闭布局:
ts
definePage({
name: "preview",
style: { navigationStyle: "custom" },
layout: false,
})一般不建议分包页面使用 layout: "tabbar",TabBar 页面应保留在主包。
分包与权限
需要登录的分包页面要配置 meta.requireAuth:
ts
definePage({
name: "advancedSettings",
style: { navigationBarTitleText: "高级设置" },
meta: { requireAuth: true },
})src/router/index.ts 会从 virtual:uni-pages 读取主包和分包页面,并把 meta 透传到路由守卫。
构建后如何检查?
构建微信小程序:
bash
pnpm run build:mp-weixin检查生成目录:
text
dist/build/mp-weixin/
├── pages/
├── subPages/
└── app.json打开 dist/build/mp-weixin/app.json,确认存在 subPackages。然后在微信开发者工具中查看:
- 代码体积分析
- 主包大小
- 分包大小
- 页面路径是否能正常打开
常见问题
| 问题 | 原因 | 处理方式 |
|---|---|---|
| 分包页面 404 | 路径写错或页面未被扫描 | 确认文件在 src/subPages 下,并使用 /subPages/... 路径跳转 |
| 页面没进分包 | 放在了 src/pages | 移到 src/subPages 对应业务目录 |
| 组件被当成页面 | 组件目录不符合排除规则 | 放到 components 目录,或补充 exclude 规则 |
| 微信上传体积超限 | 主包页面或静态资源过大 | 低频页面分包,图片走 CDN,删除无用资源 |
| 权限守卫没生效 | 没写 meta.requireAuth | 在 definePage() 中声明 meta: { requireAuth: true } |
