前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >实战篇 - 如何实现和淘宝移动端一样的模块化加载 (task-silce)

实战篇 - 如何实现和淘宝移动端一样的模块化加载 (task-silce)

作者头像
胡哥有话说
发布2019-08-05 14:04:10
7500
发布2019-08-05 14:04:10
举报
文章被收录于专栏:胡哥有话说

事情背景

事情的背景是我的实际项目,在我的实际项目当中,发现首屏渲染的速度比较慢,这样导致白屏的时间会特别长,影响用户体验度,恰好我有一天看了淘宝移动端的加载方式,针对我们的项目,就做了一次优化调整,并写了一个简单的工具库

这个工具是不限制环境和框架的,我现在的框架是 vue ,在 react 及小程序中也做过测试,是完全可以使用的,使用建议大家仔细阅读这篇文章,希望可以对你的工作有所帮助

性能优化的目的

我们每一次的界面变化,都要经历以下步骤:

image

人的眼睛大约每秒可以看到 60 帧,那么就代表我们每 16.7ms 就要看到 1 帧,一帧就要经历上图的 5 步,说明我们的每一个任务(task) 不宜过长,这样就会导致用户对于界面感知的不友好性

根据谷歌统计的数据,用户在不同时间段内接收到的反馈,可能直接影响到对于网站的用户留存,如下图:

image

在这里我们不深入讲对于这方面的一些细节,这篇文章主要是给大家讲一下,如果做任务切片,如何优化界面的渲染速度和响应速度

分析淘宝

淘宝的渲染方式

我们先看一下淘宝的渲染方式

image

通过图片和 Performancemain 部分,我们可以看得出来淘宝移动端的加载方式,是一块一块去加载的,暂时我们称之为 模块化加载

performance 的使用和如何查看性能优化的数据,可通过 性能优化篇 - Performance(工具 & api) 来了解 performance

淘宝的任务切片

image

我们放大以后可以看的出来,淘宝网在每一次的任务完成后,都会进行上面的 5 步进行界面的渲染,这样可能不如把所有的界面全部渲染完毕后,在进行样式计算、布局、绘制、计算位置等的速度快,但是这样可以保证,让用户在最短的时间内,可以看到我们的网站内容

简单的介绍一下渲染的步骤和对用户的影响,及淘宝的渲染方式,接下来我们开始实现一个任务切片的工具

任务切片源码介绍

任务切片,顾名思义就是我们要把每一个任务去做切片,缩短任务的执行时长,加快任务的渲染

这里要使用 es6 的 generator 的特性去实现任务切片

初始化任务

代码语言:javascript
复制
function init({ sliceList, callback }) {
    if (!isFunction(callback)) {
        console.error('callback 为必传参数并为 function');
        return;
    }
    // 添加切片队列
    this.generator = this.sliceQueue({
        sliceList,
        callback
    });
    // 开始切片
    this.next();
}

在一开始的时候,我们需要至少两个参数:

sliceList 或者 sliceCount : 可以是数组,也可以是数字,数组就是用来切对应的内容去分块,数字就是按次去切片

callback : 这里需要使用者传一个回调函数,用来通知使用者切片到什么位置

切片队列

代码语言:javascript
复制
function* sliceQueue({ sliceList, callback }) {
    let listOrNum = (isNum(sliceList) && sliceList) || (isArray(sliceList) && sliceList.length);
    for (let i = 0; i < listOrNum; ++i) {
        const start = performance.now();
        callback(i);
        while (performance.now() - start < 16.7) {
            yield;
        }
    }
}

由于可以接收数组和数字,所以要先做兼容处理

接下来就是核心代码其中之一了:

我们要记录回调的执行时间,如果执行需要的时间少于 16.7ms,就停止继续执行下去,释放主线程让主线程可以利用这个时间再去做别的事情

如果大于的话,就在下一次绘制的时候去执行

这个时候大家可能会比较好奇,我们为什么要对任务执行时间短的去做切片,时间长的就不切呢?

其实这个要结合下一段代码来看,大家就会了解的比较清楚了

何时执行下一个切片任务

代码语言:javascript
复制
function next() {
    const { generator } = this;
    const start = performance.now();
    let res = null;
    do {
        res = generator.next();
    }
    while (!res.done && performance.now() - start < 16.7);
    if (res.done) return;
    raf(this.next.bind(this));
}

有了这段代码,上面最后的长任务的执行没有打断就很好理解了

还是一样,任务执行的时间少于 16.7ms 就继续执行下一个切片任务

如果要是大于的话,我们就不需要执行下一个切片了,我们就要在下一次绘制(requestAnimFrame)的时候,去执行该任务,这样就可以把每一个任务给切开了

使用方法

代码语言:javascript
复制
npm install task-slice

TaskSlice.init(number || array, function(i){
    //i 执行到第几次,或者第几个切片任务
})

到这里,我们就可以模仿像淘宝一样的模块化的方式去加载,下图是我自己使用该工具库做的优化前后的数据统计:

image

image

很明显,我们的对于用户的响应速度和界面渲染速度,提升了 50% 左右。

后续

git 地址:https://github.com/nextdoorUncleLiu/task-slice

目前已发布 1.0.0 版本,下一版本可能会支持 promise 或者 控制切片时间,这个看具体的需求,及大家的反馈,我会定期进行对该工具库的更新

该工具已经在 npm 发了包,也在 git 提交了项目,有兴趣的可以去看看,顺便点个 star ,谢谢了。

结尾

已经有 n 久没有写过文章了,由于最近工作比较忙,而且项目当中对于前端性能还有架构方面的挑战性还是比较多的,这次是在做性能优化的时候,做的总结,接下来我会尽量多分享这种用于实际项目当中的优化方案,感谢大家的支持,谢谢。

还要感谢一下 berwin,是他提出的时间切片给了我灵感,这是他的 git 地址:https://github.com/berwin

致谢

再次感谢“热情的刘大爷”的投稿,喜欢作者的小伙伴可点击传送门,关注作者,与作者进一步深入交流。

投稿须知

欢迎大家多多投稿,投稿可在此公众号留言,或发送邮件到justbecoder@aliyun.com,标题格式为:胡哥有话说-投稿-文章名称,文章内容可附链接或者是md文件。

后记

以上就是胡哥今天给大家分享的内容,喜欢的小伙伴记得收藏转发、点击右下角按钮在看,推荐给更多小伙伴呦,欢迎多多留言交流…

胡哥有话说,一个有技术,有情怀的胡哥!京东开放平台首席前端攻城狮。与你一起聊聊大前端,分享前端系统架构,框架实现原理,最新最高效的技术实践!

长按扫码关注,更帅更漂亮呦!关注胡哥有话说公众号,可与胡哥继续深入交流呦!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-08-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 胡哥有话说 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 事情背景
  • 性能优化的目的
  • 分析淘宝
    • 淘宝的渲染方式
      • 淘宝的任务切片
      • 任务切片源码介绍
        • 初始化任务
          • 切片队列
            • 何时执行下一个切片任务
              • 使用方法
              • 后续
              • 结尾
              • 致谢
              • 投稿须知
              • 后记
              相关产品与服务
              云开发 CloudBase
              云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档