小程序包解包:一个 wxapkg 里到底装了什么

很多人第一次听说「解包小程序」以为是破解,其实更接近「拆开看看人家怎么组织代码」。对做前端的人来说,读一个真实上线的包,比看十篇最佳实践有用。

包是从哪来的

第一次打开某个小程序时,微信会把它下载下来,缓存在应用目录里:

安卓: /data/data/com.tencent.mm/MicroMsg/<哈希>/appbrand/pkg/
iOS : 应用沙盒内的 WeChat/AppBrand 目录

每个小程序对应一个目录,里面是若干 .wxapkg。主包之外,按需加载的分包也是一个个独立的 wxapkg。

容器格式长什么样

wxapkg 是私有格式,但结构并不复杂,可以归纳成四段:

  1. 魔数:首字节固定,用来快速识别这是不是 wxapkg;
  2. 两段长度字段:分别是索引区和数据区的字节数;
  3. 索引区:一串「文件路径 + 偏移 + 长度」的记录,相当于目录表;
  4. 数据区:所有文件的原始字节,按索引里的顺序堆在一起。

此外,索引区和数据区通常还做了一层按字节异或的混淆——不是加密,就是让 strings 扫不出明文。所以解包工具要做的事就三件:还原异或、解析索引表、按路径把数据写出去。

拆开之后看到什么

├── app-config.json      # 全局配置:pages、subPackages、tabBar
├── app-service.js       # 逻辑层,所有页面的 JS 打包在一起
├── app-wxss.js          # 样式(编译后)
├── pages/
│   ├── index/index.wxml
│   ├── index/index.wxss
│   └── ...
└── assets/              # 图片、字体、json 数据
  • app-config.json 信息量最大:能直接看到页面路由、分包划分、预加载规则、tabBar 配置。
  • 逻辑层是合并过的,变量名可能被压缩成 a、b,可读性取决于对方有没有开混淆。想读懂得靠格式化工具先展开。
  • 分包能看出人家的工程能力:主包有多大、哪些模块被拆出去按需加载,这是性能优化最直接的线索。

对开发者的实际价值

  • 学结构:看成熟产品怎么切分包、怎么组织资源目录;
  • 学体积:主包 2MB 的红线怎么守住,图片什么时候走 CDN、什么时候内联;
  • 排查自己的包:把你自己的包解开,往往能发现一堆忘记删的测试资源和重复引入的库。

几条界限

拆自己的包、拆开源示例包,随便。但拆别人的包之后:把源码改个名字重新发布、把接口地址和密钥拿去用、把私有组件抠出来塞进自己项目——这些都不只是「不地道」,是实打实的侵权,其中接口和密钥还可能涉及非法侵入计算机信息系统。

另外,包里的接口域名、token、加密盐值,很多是硬编码的。这个事实本身值得每个开发者警惕:你打进包里的东西,用户都能看到。签名算法、密钥、后台地址,一律不要放在前端。

相关阅读