codecamp

流加载是什么

用一句话来解释 流加载,那就是“下载程序包的同时加载包内的文件”,下载与加载并发可以加速小程序首次无缓存启动的时间。

为了提升小程序加载速度,我们做了下列改动:


流加载 1 期:实现下载与加载同步

使用 ttpkg 包替代 zip 包

在流加载方案之前,小程序的文件都是压缩到 zip 包内的,尽管 zip 包的体积更小,但 zip 包内的文件需要等完整的 zip 包下载好后才能解压出来使用,解压也需要时间。

在流加载方案中,我们改用 ttpkg 包来装载小程序的文件,ttpkg 包是未压缩过的二进制文件包,可以直接读取包内指定区域的二进制数据。ttpkg 包相比于压缩的 zip 包体积会更大,通过开启 CDN 智能压缩服务,在 ttpkg 包请求过程中,服务器对返回的 ttpkg 数据进行 gzip 编码,压缩重复的字符串等,可以减少 ttpkg 包的传输大小,从而缩短下载时间。

下图可见 ttpkg 包内的文件分布结构,仅举例,不同的小程序文件顺序可能不同。

图片名称

资源加载时机提前

在 ttpkg 格式程序包的支持下,我们不必等待包下载完成后才去加载资源,资源加载的时机得以提前。

流加载优化前后的启动阶段流程分别如下:

优化前

图片名称

优化后

图片名称

假设某个版本的小程序 A 在改造前后包内文件不变,资源加载顺序相同,提前加载文件可以使得小程序首屏渲染更快出现。

类似的,我们可以提前加载某些不在 ttpkg 包内的文件来减少加载文件这块的耗时,比如:

  • tma-core.js、tmg-core.js 预加载
  • page-frame.html 预加载
  • webview.js 预加载

game.js 拆分

我们还对小游戏的 game.js 文件进行了拆分,支持按需加载拆分后的 js 文件。

  • 优化前:game.js 文件包含着所有游戏场景的逻辑,这在启动阶段就会全量加载到 JSC 环境中,但实际上一些加载进来的游戏逻辑尚用不到。
  • 优化后: game.js 拆分出多个散文件,在 game.js 内根据散文件的使用先后顺序,边运行边按需加载,在理想情况下,不需要加载所有拆出的散文件即可渲染出首帧。

图片名称

如上图,优化后从 game.js 拆出了 pageA.js、pageB.js、pageC.js、pageD.js,若该小游戏仅需要加载 pageA、pageB、pageC.js 即可渲染出首屏,那我们就省下了下载以及加载 pageD.js 的时间。

副作用

当小程序无缓存冷启动,流加载的边下边加载在特定情况下也会给我们带来副作用,比如:

  • 启动阶段,ttpkg 包已下载的部分足以展示出首屏界面,但用户在操作首屏界面的过程中,忽然发生断网等问题导致 ttpkg 下载失败,此时会弹出一个报错窗口打断用户操作,用户需要重启小程序
  • 用户使用阶段, ttpkg 包中的某个图片可能因为尚未下载完,而迟迟无法展示出来;或者小游戏 ttpkg 中的某个 js 文件没下载完,而发生卡顿


流加载 2 期:小程序包体改造优化

包体改造主要是优化小程序的首屏加载时间,以下方面做了优化:

app-service.js 拆分

对齐小游戏 game.js 的拆分优化,把小程序不同界面的 js 逻辑从 app-service.js 文件中拆分出来, 各界面打开时再按需加载,减少了首屏加载过程中所需要加载的内容,可缩短首屏展示时间。

如下图所示,拆分前,app-service.js 包含拆出来的 pageA、pageB、pageC 的 js 逻辑。拆分后,首屏仅需要下载完“瘦身后”的 app-service.js 以及首页 pageA.js 再加载即可。

图片名称

WebView 预加载通用 page-frame.html、webview.js

除了实现流加载做到下载与加载并发来缩短首屏展示时间外,在文件加载阶段,我们会把某些特定文件提前预加载好,并且确保这些文件不在 ttpkg 包内,这样就不会被 ttpkg 下载过程所影响。

最佳理想情况下,可达到的效果图:

图片名称

WebView 的创建、page-frame.html 和 webview.js 的加载都是必须的操作,所以在小程序启动前预创建、预加载好,可以一定程度减少小程序启动后再去加载他们的消耗的时间。

为了能做到预加载,流加载二期,就把 ttpkg 中的 page-frame.html(它包含所有界面的结构)精简成各界面通用的 page-frame.html, 并放到我们的 jssdk 基础库中。而 jssdk 基础库都是内置在 SDK 中的,不强依赖于下载过程。


流加载 3 期:ttpkg 包中文件分布顺序的优化

为了达到流加载的最大收益,我们还在要做 ttpkg 包中文件分布顺序的优化。

举个例子,如下是某个小游戏 ttpkg 包文件分布图,从低到高位分别安放着以下文件:

图片名称

当游戏启动后,ttpkg 下载的大小刚好包含 game.js 文件,于是小游戏开始加载执行 game.js, 但 game.js 中又去加载了 gameB.js,这种情况下,小游戏就会停止等待 ttpkg 继续下载,直到包下载大小超过了 gameB.js 才会继续执行。

ttpkg 包内文件分布顺序 的优化就是为去调整文件在 ttpkg 包中的坐落位置,尽可能让文件分布顺序与小程序/游戏启动执行要加载的文件顺序一致。这样就可以减少在启动无缓存小程序的过程中, 出现要加载某个尚未下载到的文件而停止等待的场景。

后台每日根据上报的文件访问顺序埋点,按顺序以及频率进行排序,优化 ttpkg 的文件顺序,生成新的 ttpkg。该操作无需开发者做任何操作。

场景值
流加载与分包加载的区别
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

字节跳动小程序 介绍

字节跳动小程序 开发

字节跳动小程序开发框架

字节跳动小程序开发框架基础说明

字节跳动小程序开发框架基础功能

字节跳动小程序开发框架逻辑层

无标题文章

无标题目录

API

无标题文章

无标题文章

无标题文章

无标题文章

无标题文章

无标题目录

无标题目录

无标题文章

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }