2、包体积优化(上):代码压缩与混淆、图片资源压缩(WebP/AVIF)、无用代码与资源清理
包体积优化,说白了就是给小程序「减重」。我见过太多团队,功能做了一大堆,结果包体积飙到 2MB、3MB,用户加载慢得想摔手机。其实很多体积都是「虚胖」——代码里藏着大量注释、冗余变量,图片还是几年前的 PNG 格式。今天咱们就从上手最快的三个方向开刀:代码压缩与混淆、图片格式升级、以及清理那些「僵尸代码」。
2.1 代码压缩与混淆:把「废话」去掉
代码压缩,就是把变量名缩短、去掉空格和注释。混淆则更进一步,把函数名、变量名改成 a、b、c 这种短名。两者配合,体积能直接砍掉 30%-50%。
我习惯在构建阶段用工具自动处理。微信开发者工具自带「上传时压缩代码」选项,但说实话,它只做了基础压缩。想要更狠的效果,得自己配 Webpack 或 Gulp。
核心思路:压缩后的代码,人类读不懂,机器跑得欢。这就够了。
2.1.1 使用 TerserPlugin 做深度压缩
Webpack 项目里,我最常用 TerserPlugin。它能把代码体积压到极限。配置起来也不复杂:
// webpack.config.js
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
drop_console: true, // 干掉所有 console.log
drop_debugger: true, // 去掉 debugger 语句
pure_funcs: ['console.log'] // 彻底移除
},
mangle: true, // 混淆变量名
output: {
comments: false // 去掉注释
}
}
})
]
}
};
这里有个坑:drop_console: true 会干掉所有 console 语句。我在项目中遇到过,上线后线上问题排查不了,因为所有日志都没了。后来我改成只保留 console.error:
compress: {
pure_funcs: ['console.log', 'console.info', 'console.warn']
}
注意:混淆后的代码,报错堆栈会变成 a、b、c。记得上传 sourcemap 到监控平台,否则线上报错你根本看不懂。
2.1.2 微信小程序原生压缩配置
如果你用原生开发,可以在 project.config.json 里开启:
{
"setting": {
"uglifyFileName": true, // 压缩文件名
"minified": true, // 压缩代码
"es6": true, // ES6 转 ES5
"postcss": true // 自动补全 CSS 前缀
}
}
嗯,这里要注意:es6: true 会转译语法,但也会增加一些 polyfill 代码。如果你的基础库版本够新(2.15.0+),可以关掉它,直接用原生 ES6 支持,反而能省点体积。
2.2 图片资源压缩:WebP 和 AVIF 是王道
图片往往是包体积的「大头」。我见过一个小程序,光图片就占了 1.2MB,其中大部分是 PNG 和 JPEG。你想想看,现在手机屏幕都是视网膜屏,一张 200KB 的 PNG 在 1x 图上根本看不出区别。
我个人习惯,能转 WebP 就转 WebP。如果条件允许,AVIF 更香。来看对比:
| 格式 | 压缩率(相对 PNG) | 浏览器支持 | 适用场景 |
|---|---|---|---|
| PNG | 基准 | 全部 | 需要透明背景的图标 |
| JPEG | 约 60% | 全部 | 照片、渐变图 |
| WebP | 约 30% | 微信 7.0+、Chrome | 大部分场景,推荐 |
| AVIF | 约 20% | 微信 8.0+、Chrome 85+ | 高压缩需求,注意兼容 |
2.2.1 批量转换 WebP
我一般用 cwebp 命令行工具,配合脚本批量处理:
# 安装工具
brew install webp
# 批量转换所有 PNG 和 JPG
for file in images/*.{png,jpg,jpeg}; do
cwebp -q 80 "$file" -o "${file%.*}.webp"
done
-q 80 是质量参数。我测试过,80 的视觉损失几乎不可察觉,但体积能降 70%。如果你对图片质量要求极高,可以调到 90。
小技巧:微信小程序里,<image> 标签直接支持 WebP。你只需要把图片后缀改成 .webp,路径写对就行。不需要额外配置。
2.2.2 AVIF 的「坑」与「甜」
AVIF 压缩率确实牛,但我在项目中遇到过兼容问题。微信 8.0 以下版本不支持,部分 Android 机型也会闪退。我的做法是「降级方案」:
// 判断是否支持 AVIF
function supportsAvif() {
const canvas = document.createElement('canvas');
return canvas.toDataURL('image/avif').indexOf('data:image/avif') === 0;
}
// 动态选择图片格式
const imgSrc = supportsAvif() ? 'photo.avif' : 'photo.webp';
说白了,AVIF 是未来,但现在还不是全部。我建议主力用 WebP,AVIF 作为「锦上添花」。
2.3 无用代码与资源清理:别让「僵尸」占地方
项目迭代久了,代码里会积累大量「僵尸」——废弃的页面、没用的组件、注释掉的代码块。这些东西不会报错,但会白白增加包体积。
我曾经接手过一个项目,里面竟然有 5 个版本的登录页面,只有 1 个在用。删掉之后,包体积直接少了 200KB。你想想看,这 200KB 要是用来放新功能多好。
2.3.1 使用 ESLint 检测未使用变量
ESLint 的 no-unused-vars 规则能帮你揪出「死代码」:
// .eslintrc.js
module.exports = {
rules: {
'no-unused-vars': ['error', {
vars: 'all', // 检查所有变量
args: 'after-used', // 只检查未使用的参数
ignoreRestSiblings: true
}]
}
};
配合 eslint --fix 可以自动删除未使用的 import。但要注意,有些变量是「全局引用」的,比如挂在 wx 对象上的方法,ESLint 可能误报。这时候加个注释忽略就行:
// eslint-disable-next-line no-unused-vars
const unusedVar = '这个变量确实没用,但我先留着';
警告:别用 /* eslint-disable */ 全局关闭规则。那等于掩耳盗铃。我见过有人为了省事,直接关掉所有规则,结果代码里一堆死变量,包体积越来越大。
2.3.2 清理无用图片和字体文件
图片资源最容易「藏污纳垢」。设计师经常往项目里丢一堆「备选图」,结果从来没用过。我的做法是:
- 全局搜索引用:在 IDE 里搜索图片文件名,看有没有被引用。
- 使用工具扫描:
unused-webpack-plugin可以自动找出未引用的资源。 - 定期清理:每个迭代结束,跑一次清理脚本。
// webpack.config.js 中配置
const UnusedWebpackPlugin = require('unused-webpack-plugin');
plugins: [
new UnusedWebpackPlugin({
directories: [path.join(__dirname, 'images')],
exclude: ['*.ico'], // 排除 favicon
root: __dirname
})
]
跑完构建,控制台会列出所有未使用的文件。嗯,这时候别手软,直接删。
2.3.3 删除注释掉的代码块
很多人习惯把旧代码注释掉,想着「以后可能用」。说实话,我从来没见过谁真的回头去翻那些注释。Git 历史里都有,怕丢就提交一次再删。
我建议用正则全局搜索 /\*[\s\S]*?\*/ 和 //.*,把大段注释干掉。但要注意,有些注释是文档说明,比如函数用途、参数含义,这些得保留。
我的原则:注释只解释「为什么」,不解释「是什么」。代码本身应该能说明「是什么」。如果代码读不懂,那是代码的问题,不是注释的问题。
2.4 实战:一个完整的优化流程
说了这么多,咱们串起来走一遍。假设你有一个 1.5MB 的小程序,目标是压到 1MB 以内:
- 先跑分析工具:用微信开发者工具的「代码依赖分析」,看看哪些文件最大。
- 压缩代码:配置 TerserPlugin,开启
drop_console和mangle。这一步能省 200KB-300KB。 - 转换图片:把所有 PNG/JPEG 转成 WebP,质量设 80。这一步能省 300KB-500KB。
- 清理僵尸:删掉未使用的页面、组件、图片。这一步能省 100KB-200KB。
- 验证功能:压缩和混淆后,一定要跑一遍核心流程。我遇到过混淆把
wx.navigateTo的参数搞乱的情况。
做完这四步,1.5MB 降到 800KB 是很常见的。用户加载速度从 3 秒降到 1.5 秒,体验提升是实打实的。
最后提醒:包体积优化不是一锤子买卖。我建议每次发版前都跑一遍分析工具,把「增重」的部分揪出来。养成习惯,你的小程序会一直保持「苗条」。
下一章咱们聊「包体积优化(下)」,重点讲分包策略和动态加载。那些才是真正的大招,能把 2MB 的包拆成几个 500KB 的小包,用户打开速度直接起飞。