本文是对上次公众号发文《微信小程序逆向源码深度揭秘》 (opens new window)的扩展,着重探究小程序包的主要内容构成。
# 先有鸡还是先有蛋?谈谈小程序包的产生与消亡
任何事物都是有生命周期的,小程序包也不例外,为了方便理解,我们暂且叫它【小程序包的生命周期】。其实本没有这个概念,只是为了本文的理解才引入了这么一个概念。
这里大致归纳为以下几个阶段。
- 产生:苦逼的程序猿们接到领导的需求,火速开发小程序,最后在微信开发者工具中点击【上传】按钮完成小程序包的打包上传,至此一个体验版小程序包(需要后台手动设置版本为体验版)就此在微信的服务器上诞生了。
- 传播:提交审核通过之后小程序包会被分发到CDN网络,供用户下载。
- 使用:用户通过某种渠道打开小程序就会把小程序包下载到本地进行解压使用。
- 归宿:用户们玩腻了在微信主页顶端下拉菜单中长按小程序并拖进垃圾桶。。(最终归于尘土 ಥ_ಥ)
这里需要注意的是:同一小程序分开发版、体验版、正式版,几个包都是独立,互相隔离的,并且缓存(优先加载)在本地。普通用户看到的只是正式版。
# 用户初次打开小程序时发生了什么?
在小程序启动时,微信会为小程序展示一个固定的启动界面,界面内包含小程序的图标、名称和加载提示图标。
微信会做以下工作:
- 下载小程序代码包
- 加载小程序代码包
- 初始化小程序首页
# 包文件结构介绍与打包规则
关于文件结构这里不再赘述(不是本文关注重点)
这里简要提一下微信小程序包的文件格式,注意是『微信』哦。
格式:
文件头+文件名+文件内容起始地址及长度
注意:
- 微信小程序包文件头信息是以
0xbe
开头,所以如果你拿了抖音的小程序包来解是没用的 - 文件内容都是明文存放的,这是我们能够顺利解包的前提
接着我们回过来来看看解包后文件的主要构成,这里还是拿开源中国的小程序开刀吧🤫😈。
为了辅助理解,我们先修改源码中的 wuWxapkg.js
文件,L34(34行)后面追加下面的代码
console.log(`No.${i+1}:`, info.name);
然后执行以下命令得到日志
node wuWxapkg.js -o osc.wxapkg
通过观察文件名列表我们可以看出:
包内主要包含
①静态资源->static/**、图片、svg......
②app-config.json
③app-service.js
④page-frame.html
⑤页面html文件->pages/**.html、其它组件或者页面的html
关键文件作用整理如下:
文件名 | 作用 |
---|---|
app-config.json | 小程序完整的配置,包含我们通过app.json里的所有配置,综合了默认配置 |
app-service.js | 各页面的JS代码 |
page-frame.html | 小程序视图(渲染页面)的模板文件,所有的页面都使用此加载渲染,且所有的WXML都拆解为JS实现打包到这里 |
**.html | 其它页面的html |
主包一般都是2M左右大小,也有特别的会达到4M+
未列进来的文件:
文件名 | 作用 |
---|---|
WAService.js | 逻辑层基础库文件,提供逻辑层基础能力 |
WAWebview.js | 视图层基础库文件,提供视图层基础能力 |
WAConsole.js | 控制台基础库 |
解出来之后如果得到包含这几个文件的内容,就说明解的不是主包。
我们顺带看看微信开发者工具源码中的 pageframe.html
在mac系统下可以通过『微信开发者工具』上右键菜单点击显示包内容来找到这个模板文件,文件路径:
/Applications/wechatwebdevtools.app/Contents/Resources/package.nw/html
<!-- -->
部分即是模板字符串,会在执行过程中被动态替换
# 得出的一些结论
- 基础库是内置在微信客户端的,在用户本地会有缓存,打开小程序时如果本地存在缓存则优先加载,所以如果在开发模式下开启了调试模式没有关闭则打开正式版也会出现绿底白字的『console』悬浮按钮。
- 微信小程序包的文件头是以 oxbe 开头,所以如果不是则认为不是微信家的小程序包
- page-frame.html 是小程序运行时模板文件,所有视图层页面内容的加载都是基于这个模板html文件(从微信开发者工具源码也可以略知一二)进行模板字符串替换
- 所有的业务逻辑代码都是打包到 app-service.js 文件
注:以上内容仅是博主学习了相关资料结合个人理解整理所得,不免会有疏漏的地方,如有更好的发现,欢迎交流。