微信小程序主包上限 2MB、整包上限 30MB(个别类目 20MB),这是所有小程序团队绕不开的天花板。我们交付的校园点餐小程序曾把主包压到 1.98MB 的悬崖边,最终通过分包架构降到 0.9MB,启动时间缩短约 40%。本文给出完整可落地的操作路径。
一、先体检:体积都花在哪里了
在微信开发者工具中点击"代码依赖分析",能看到每个文件占比。常见元凶排序:
- 图片资源占 50% 以上——最典型的问题。本地打包的 PNG/Banner 图动辄几百 KB 一张
- 未按需引入的组件库——整包引入 Vant Weapp / TDesign,实际只用了三五个组件
- 重复的工具函数——多个
utils文件互相拷贝 - ES6 转 ES5 后的冗余——关闭"上传代码时样式自动补全"等可减少体积
第一步永远是:把所有静态图片迁移到 CDN(对象存储 + CDN 域名),代码里只留 URL。仅此一步通常减少 40%~70% 体积。
// ❌ 错误:图片放进项目 /images 目录随包上传
<image src="/images/banner-home.png" />
// ✅ 正确:CDN 地址,主包零负担
<image src="https://cdn.example.com/banner-home.webp" />
二、分包配置:主包只留"启动必需"
分包的核心思想:主包只放 tabBar 页面和公共代码,其余业务按模块拆进 subpackage。
{
"pages": [
"pages/index/index",
"pages/menu/menu",
"pages/mine/mine"
],
"subpackages": [
{
"root": "pkg-order",
"pages": [
"confirm/confirm",
"detail/detail",
"history/history"
]
},
{
"root": "pkg-admin",
"pages": [
"dashboard/dashboard",
"stats/stats"
]
}
],
"preloadRule": {
"pages/menu/menu": {
"network": "wifi",
"packages": ["pkg-order"]
}
},
"lazyCodeLoading": "requiredComponents"
}
三个关键点:
- 公共代码放主包:分包可以引用主包的 js/组件,反过来不行。跨分包共享的工具建议通过主包
app.js挂载或使用分包异步化 - preloadRule 预下载:用户浏览菜单(主包)时,WiFi 环境提前拉取点餐分包,点"去结算"零等待
- lazyCodeLoading 必开:默认注入全部自定义组件代码,开启后只注入当前页用到的组件,对页面多的项目立竿见影
三、独立分包:营销页的启动加速器
独立分包不依赖主包,扫码直达时不需要先下载主包。活动页、推广落地页放进独立分包,冷启动速度可以快一倍以上:
{
"root": "pkg-activity",
"independent": true,
"pages": ["invite/invite", "coupon/coupon"]
}
注意约束:独立分包内不能引用主包的公共代码、不能使用 getApp()(需判空),登录态等逻辑要自带。
四、进阶压缩手段清单
| 手段 | 效果 | 备注 |
|---|---|---|
| 图片转 WebP | 体积减 30%~50% | iOS/安卓基础库 2.9+ 均支持 |
| 关闭 sourcemap 上传 | 减 10%~20% | 项目设置里关闭"上传时带 sourceMap" |
| 组件库按需引入 | 视用量 | Vant Weapp 天然按需;整包引 UI 的自查 |
| 分包异步化 | 主包再瘦身 | 组件跨分包引用(基础库 2.17.3+) |
| wxml/wxss 混淆压缩 | 减 5%~15% | 开发者工具"上传压缩"全开 |
五、上线前的体积纪律
体积管理是持续过程,建议固化两条规则进 CI:
- 上传前跑体积脚本:用
miniprogram-ci的preview接口拿到包体积,超过阈值(如主包 1.6MB)直接告警 - 图片一律走 CDN 审计:CI 里扫描
.wxml与js中的本地图片路径,发现即构建失败
// scripts/check-size.js(配合 miniprogram-ci)
const ci = require('miniprogram-ci');
const project = new ci.Project({
appid: 'wxXXXXXX',
type: 'miniProgram',
projectPath: './dist',
privateKeyPath: './private.key',
});
ci.preview({ project, desc: 'size-check' }).then((r) => {
const size = r.subPackageInfo ?? [];
console.log(JSON.stringify(size, null, 2));
// 解析主包大小,超阈值 process.exit(1)
});
小结
包体积治理的优先级:图片出包 → 分包拆分 → 按需注入 → 预下载策略 → CI 体积门禁。按这个顺序执行,2MB 限制从"随时爆雷的炸弹"变成"再也不会看一眼的数字"。