4、包体积优化(下):分包加载策略,独立分包与分包预加载,主包与分包的最佳实践
好,咱们接着聊包体积优化。上一节我把代码层面的“瘦身”方法讲得差不多了,这一节咱们聚焦在加载策略上。
说白了,包再小,如果加载方式不对,用户还是得干等着。我见过不少项目,主包就2M,但启动时把所有逻辑都塞进去,结果首屏渲染慢得让人抓狂。嗯,这里的关键就是分包。
4.1 分包加载:把“大礼包”拆成“小零食”
小程序默认有个限制:整个包不能超过16M,主包不能超过2M。但很多业务复杂的项目,光一个主包就快撑爆了。
怎么办?拆!
分包加载的核心思想是:用户打开小程序时,只下载主包和当前页面所在的分包。其他分包,等用户真正访问时再下载。
核心原则:主包只放核心逻辑和公共组件,业务页面全部分包化。
举个例子,一个电商小程序:
- 主包:首页、登录、购物车(核心流程)
- 分包A:商品详情、评价、推荐
- 分包B:个人中心、订单、售后
- 分包C:秒杀、拼团、优惠券
配置方式很简单,在 app.json 里声明:
{
"pages": [
"pages/index/index",
"pages/login/login"
],
"subPackages": [
{
"root": "packageA",
"pages": [
"pages/detail/detail",
"pages/review/review"
]
},
{
"root": "packageB",
"pages": [
"pages/order/order",
"pages/after-sale/after-sale"
]
}
]
}
这样配置后,用户打开首页,只下载主包。只有点击商品详情时,才去下载 packageA。首屏加载速度能提升30%以上,我在项目中实测过。
我的习惯:每个分包的大小控制在500KB以内。超过这个数,我会考虑再拆一层。
4.2 独立分包:让某些页面“自给自足”
分包加载虽然好,但有个问题:访问分包页面时,主包必须已经加载完成。如果主包很大,用户从外部链接直接跳转到分包页面,还是得等主包下载完。
独立分包就是来解决这个问题的。
独立分包可以不依赖主包,单独运行。它有自己的页面、组件、甚至逻辑。用户从外部跳转进来,直接下载独立分包就行,主包可以后面再加载。
配置方式:
{
"subPackages": [
{
"root": "packageIndependent",
"pages": [
"pages/activity/activity"
],
"independent": true
}
]
}
注意,independent: true 就是关键。
我曾经踩过的坑:独立分包里不能引用主包的资源(图片、样式、JS等)。如果你在独立分包里用了主包的公共组件,那独立分包就失效了,还是会去加载主包。所以,独立分包里的东西,必须完全自包含。
什么场景适合用独立分包?
- 活动页面:比如双11秒杀页,用户从广告链接直接进来,越快展示越好。
- 分享落地页:用户从微信聊天里点开分享卡片,直接进入某个商品详情。
- 紧急修复页:主包有bug来不及发版,用独立分包做个临时页面顶上。
4.3 分包预加载:提前“偷跑”,让用户感觉不到加载
分包加载虽然减少了首屏体积,但有个副作用:用户点击跳转时,如果目标页面在另一个分包里,会有短暂的下载等待。
怎么消除这个等待?预加载。
分包预加载的意思是:在当前页面加载完成后,提前下载用户可能访问的下一个分包。
配置方式:
{
"preloadRule": {
"pages/index/index": {
"network": "all",
"packages": ["packageA"]
},
"pages/detail/detail": {
"network": "wifi",
"packages": ["packageB", "packageC"]
}
}
}
这里我解释一下:
network: "all"表示任何网络下都预加载。适合核心分包。network: "wifi"表示只在WiFi下预加载。适合非核心分包,省流量。
我个人习惯是:用户进入首页后,立刻预加载最常用的那个分包。比如电商小程序,首页加载完,后台就开始下载商品详情分包。用户点击商品时,分包已经准备好了,体验非常丝滑。
避坑指南:预加载不是越多越好。如果你预加载了3个分包,每个500KB,那用户一进来就要下载1.5MB,反而拖慢了首屏。我建议只预加载1-2个最核心的分包。
4.4 主包与分包的最佳实践
讲了这么多,最后总结一下我这些年总结出来的“黄金法则”:
| 维度 | 最佳实践 | 说明 |
|---|---|---|
| 主包内容 | 只放核心框架、公共组件、全局样式 | 主包大小控制在1.5MB以内,留点余量 |
| 分包粒度 | 按业务模块拆分,每个分包300-500KB | 太细了管理麻烦,太粗了加载慢 |
| 独立分包 | 只用于活动页、落地页、紧急修复页 | 不要滥用,独立分包不能共享主包资源 |
| 预加载策略 | 首屏加载后预加载1-2个核心分包 | 非核心分包用WiFi下预加载 |
| 公共资源 | 图片、字体、工具库尽量放主包 | 避免每个分包都重复打包同一份资源 |
嗯,这里有个细节我想强调一下:公共组件到底放主包还是分包?
我的建议是:如果这个组件被3个以上分包使用,就放主包。如果只被1-2个分包使用,就复制到对应分包里。为什么?因为放主包虽然省了重复代码,但增大了主包体积,影响首屏加载。这是个权衡问题。
一个小技巧:用微信开发者工具的「代码依赖分析」功能,看看哪些模块被多个分包引用。如果发现某个工具函数被5个分包都引用了,果断提到主包。
最后,我想说一句:分包不是银弹。你想想看,如果业务逻辑本身就很复杂,再怎么分包也解决不了根本问题。真正的优化,是从产品设计阶段就开始考虑:哪些功能是核心路径?哪些可以延迟加载?
我见过一个项目,为了追求分包极致,把登录页都拆到独立分包里去了。结果用户从外部跳转进来,登录页是秒开了,但登录后要跳回主包,反而多了一次加载。得不偿失。
所以,一切优化都要以用户体验为最终目标。包体积小了,加载快了,用户觉得爽,这才是王道。