9 月初,微信开发者工具里的构建结果又飘红了:主包 2.3M,超过 2M 上限,真机预览直接传不上去。
2018 年我们给这个茶叶小程序做过一次瘦身,从 1.9M 压到 1.1M,当时还写了篇东西记怎么量的。六年过去,又回来了。去翻了一下这六年加过什么,挺有意思。
先量,别猜
老规矩,先定怎么量。开发者工具的「代码依赖分析」导一份,再拿构建产物里每个文件按大小排个序,落到一张表里。不看总量,看谁占的。
排完前几名:
- 一套图表库,打包进来 380K,只在「销售趋势」一个页面用。
- lodash 全量引入,实际用到 4 个方法,占 70K 出头。
- 一个日期处理库,跟小程序自带的格式化重复了。
- 三张早年活动留下的 PNG,早没入口了,还躺在主包目录里。
- 三个页面:2019 年做的「积分商城」、2021 年的「门店导航」、还有一个从没上过线的「问卷调查」。
图片这次不是主角,六年前那套 CDN 加 webp 还在起作用。真正长出来的是依赖和页面,都是一次次「顺手加一下」攒的。
第一步:清没人用的
最好剪的是死代码。三个页面先确认还有没有人进:拉半年小程序后台的页面访问数据,积分商城 11 次、门店导航 0 次、问卷调查 0 次。11 次那个我们没删,移到分包里;两个 0 次的直接下掉,代码留 Git 历史,不留在包里。
那三张 PNG 删掉,90 多 K。
这一步最舒服,不用跟谁商量,删完包就小了一截。
第二步:依赖清点
5 个 npm 包,逐个问「在哪用、能不能自己写」。
lodash 用了 debounce、get、groupBy、cloneDeep 四个。换成四个手写函数,加起来不到 60 行,省了 70K。不是反对用库,是这个小程序真就只用到这么点。
日期库直接删,小程序端用 js 原生 Date 加一个 20 行的格式化函数就够,服务端返回的本来就是格式化好的字符串。
图表库最麻烦。它只在「销售趋势」页用,但那个页面在主包里。先把它移到分包,再顺手换成一套轻量的 canvas 画法,只画折线和柱状两种,代码 100 多行。体积从 380K 降到 40K 不到,样子客户看了一眼说没差。
这里踩了个坑:小程序分包之间不能互相引用自定义组件,图表组件原先被两个页面共用,拆的时候得复制一份到分包目录,或者提到主包。我们选了后者,公共组件留主包,图表这种只在分包用的就放分包里,别为了「复用」把东西全往上堆。
第三步:分包结构重排
2018 年那版是主包加一个分包。六年下来,那个分包自己长到了 1.4M,而且里面混着低频和高频的东西。
重排成主包加 3 个分包:
- 主包:首页、分类、商品详情、购物车、登录,还有必须全局的公共组件。
- trade 分包:订单列表、订单详情、售后、积分商城。
- user 分包:个人中心、地址、发票、收藏。
- misc 分包:品牌介绍、帮助、活动存档、销售趋势。
分包预下载配了 3 条规则,进首页后闲时拉 trade,进个人中心前拉 user。misc 不预下载,真有人点再等一下。
主包里还留了个历史包袱:早期有个 utils 被主包和全部分包都引了,之前提过一次,这次发现又被复制了两份。统一提到主包,加了一条构建检查,扫到重复打包就报警。
第四步:按路由懒加载
有些逻辑不是页面,是「一进小程序就初始化」的东西:埋点 SDK、一个统计上报、还有登录态检查。原来全写在 app.js 的 onLaunch 里,首屏要等它们跑完。
改成按需:埋点在第一个页面 onShow 之后再初始化,统计上报丢到空闲回调,登录态检查保留但只做一次轻量校验。这几步不减包体积,减的是首屏时间。
数据
改完构建,主包 1.1M 时代的那套量法又拿出来用了一遍:真机 20 次取中位数。
- 主包 2.3M 到 1.8M,离 2M 留了 200K 余量。
- 三个分包加起来 1.6M,比原来那个混装的分包还小一点。
- 首屏中位数 2.1 秒到 1.6 秒,最慢一次 2.0 秒。
- 那个只在趋势页用的图表,现在首屏根本不加载了。
没换框架,没加机器,主要还是删和挪。
问:为什么不一次到位
有人问,六年前压到 1.1M,怎么又让它长回来。
说实话,没有哪一次提交是错的。加个图表库是因为要一个趋势图,加个问卷页是因为当时说要收反馈,每个都有理由。包体积这种东西,不盯着就会慢慢长,跟抽屉一样。
这次做完加了一条构建卡点:主包超过 1.9M 就构建失败,不等到传不上去才发现。还有一条写在 README 里,加依赖之前先看一眼依赖分析那张表。
9 月 6 号下午收工,构建结果从红的变回绿的。有人把两次的截图并排贴在文档里,左边 2018,右边 2024,中间隔着六年和一堆顺手加的东西。

