神族九帝's blog 神族九帝's blog
首页
网盘 (opens new window)
线报 (opens new window)
商城 (opens new window)
  • 复习指导
  • HTML
  • CSS
  • JavaScript
  • 设计模式
  • 浏览器
  • 手写系列
  • Vue
  • Webpack
  • Http
  • 前端优化
  • 项目
  • 面试真题
  • 算法
  • 精选文章
  • 八股文
  • 前端工程化
  • 基础篇
  • 进阶篇
  • 高级篇
  • 计算机基础
  • 高频考点
  • 精简题
  • 综合问题
  • 复习题
  • vue
  • vue2源码学习
  • 剖析vuejs内部运行机制
  • TypeScript 入门实战笔记
  • vue3源码学习
  • 2周刷完100道前端优质面试真题
  • npm发包
  • 重学node
  • 前端性能优化方法与实战
  • webpack原理与实战
  • webGl
  • 前端优化
  • Web3
  • 更多
  • 网站
  • 资源
  • Vue资源
  • 收藏的一些API
  • 未来要做的事
  • 宝塔面板+青龙面板
  • 安卓手机当服务器使用
  • 京东自动评价代码
  • 搭建x-ui免流服务器(已失效)
  • 海外联盟
  • 好玩的docker
  • 导航
GitHub (opens new window)

神族九帝,永不言弃

首页
网盘 (opens new window)
线报 (opens new window)
商城 (opens new window)
  • 复习指导
  • HTML
  • CSS
  • JavaScript
  • 设计模式
  • 浏览器
  • 手写系列
  • Vue
  • Webpack
  • Http
  • 前端优化
  • 项目
  • 面试真题
  • 算法
  • 精选文章
  • 八股文
  • 前端工程化
  • 基础篇
  • 进阶篇
  • 高级篇
  • 计算机基础
  • 高频考点
  • 精简题
  • 综合问题
  • 复习题
  • vue
  • vue2源码学习
  • 剖析vuejs内部运行机制
  • TypeScript 入门实战笔记
  • vue3源码学习
  • 2周刷完100道前端优质面试真题
  • npm发包
  • 重学node
  • 前端性能优化方法与实战
  • webpack原理与实战
  • webGl
  • 前端优化
  • Web3
  • 更多
  • 网站
  • 资源
  • Vue资源
  • 收藏的一些API
  • 未来要做的事
  • 宝塔面板+青龙面板
  • 安卓手机当服务器使用
  • 京东自动评价代码
  • 搭建x-ui免流服务器(已失效)
  • 海外联盟
  • 好玩的docker
  • 导航
GitHub (opens new window)
  • vue2源码学习

  • 剖析vuejs内部运行机制

  • TypeScript 入门实战笔记

  • vue3源码学习

  • 2周刷完100道前端优质面试真题

  • npm发包

  • 重学node

  • 前端性能优化方法与实战

    • 00 开篇词 开启刻意练习之路,进阶前端性能技术专家
    • 01 体系总览:性能优化体系及关键指标设定
    • 02 性能瓶颈点:从 URL 输入到页面加载整过程分析
    • 03 案例分析:移动端 M 站性能优化落地注意事项
    • 04 指标采集:首屏时间指标采集具体办法
    • 05 指标采集:白屏、卡顿、网络环境指标采集方法
    • 06 工具实践:性能 SDK 及上报策略设计
    • 07 平台实践:如何从 0 到 1 搭建前端性能平台
    • 08 诊断清单:如何实现监控预警并进行问题诊断
    • 09 优化手段:首屏秒开的 4 重保障
    • 10 优化手段:白屏 300m 和界面流畅优化技巧
    • 11 工具实践:如何进行性能专项测试
    • 12 理论分析:Hybrid 下的性能优化整体分析
    • 13 高级进阶:保证首次加载为秒开的离线包设计
    • 14 高级进阶:瞒天过海的骨架屏及 SSR 优化手段
    • 15 高级进阶:WebView 层及代码架构层面优化
    • 16 黑科技:详解预请求、预加载及预渲染机制
      • 17 横向对比:百度、阿里云、美团性能方案对比
      • 18 性能演进:RN、Flutter、小程序和 Enhance Hybrid
      • 19 成长之路:前端技术专业能力与业务产出平衡
      • 20 结束语 开启性能优化实践之路
    • webpack原理与实战

    • webGl

    • 前端优化

    • Web3

    • 更多

    • 学习笔记
    • 前端性能优化方法与实战
    wu529778790
    2021-09-20

    16 黑科技:详解预请求、预加载及预渲染机制

    前面好几讲我介绍过怎么进行首屏时间优化,但其实在性能影响因素里,后端接口的耗时也不可忽略。

    以某电商 App 列表页为例,后端接口返回数据需要 200ms,参考首屏秒开的标准,它就占了 20% 的时间。在以前我一直采用的是缓存或者静态化的方案去解决,能不请求实时数据就不请求,用历史数据去代替。

    直到有一天,我遇到了机票和酒店相关的业务,因为它们的价格和库存会实时变化,如果页面打开时间长(首屏时间过长),用户会担心买不到合适的机票,转而离开去往竞品购买(机票和酒店类产品的留存率很低,用户忠诚度有限)。为了避免这种情况,我必须实时拉取后端接口,做到极致秒开。但具体怎么解决呢?我一直没想好,直到 19 年才有了解决方案。

    那就是采用预请求、预加载和预渲染的方式来解决问题。所谓预请求,就是对后端请求参数的事先拼装,预加载是指对后端数据接口的提前加载,预渲染则是对要渲染页面预先进行渲染。接下来我就为你详细介绍下它们,希望对你有所帮助。

    预请求

    想要通过拉取后端接口来降低首屏时间,我们需要先实现接口的预加载。而实现它要先解决预请求的逻辑,也就是统一拼装请求参数的逻辑。

    具体怎么进行统一拼参呢?这就涉及前端正常的数据请求过程了。

    以机票业务为例,我们进入列表页后,输入出发地和目的地后,比如从北京到深圳,选择日期为 2021-06-06,前端应用通过解析页面 URL 路径,拿到所需的一些参数(如 from=shanghai&to=beijing&date=20210606),然后调用 Native 的 schema 进入参数解析环节,找到 Native 对应的协议和参数(如://search?terminal=app),然后再通过参数初始化,拼装成对应的参数(如://search?terminal=app&from=shanghai&to=beijing&date=20210606)。

    如果预请求走上述流程的话,面临的一个问题是,没有预请求的页面 URL 参数,也没法通过 Native 获取到。这需要自己根据逻辑拼装,所以往往会单独做出一套流程,结果就是不但容易出错,还会因为需要用类似两份代码去实现这个功能,反过来拉长页面的首屏时间。所以,我们使用了同样的流程,将预请求封装成preReq 功能,把所有的功能都包括起来,用同一份代码实现。

    在做完这个统一拼参逻辑后,预请求实现起来就容易了。具体来说,如果你已经使用了 Native 统一请求,直接走客户端逻辑发送即可。如果还没有走 Native 统一请求,

    我们可以借助Axios 库函数来完成。

    第一步,我们需要封装一下 Axios 库函数,在 post 和 get 之前,通过添加一个钩子函数 BeforeFetch,对 URL 参数进行解析和 Native 参数补全。

    第二步,业务侧使用与请求时,因为 Axios 库是整体打包引入的,所以使用时,可以直接使用 Axios.fetch 方法来实现预请求功能。

    预加载

    在完成预请求参数拼装之后,紧接着就是预加载逻辑了。首先是要把握预加载的时机。以机票列表页为例,我们需要判断用户操作的特定路径。如果用户操作命中了这个特定路径,就会做预加载,去请求列表页的接口。

    这个路径是我们和后端的一个约定,有具体的编号,比如用户“进入首页”编号是 0,“输入出发地和目的地”操作路径是 1,“输入日期”操作路径是 2,“切换关键词”是 3,点击“我的位置”是 4。

    后端在用户进入列表页时,以接口的方式返回一个操作路径的数组,当用户的操作路径命中这个数组后,比如 [1,2,3],意思是用户从首页进入,选择了出发地和目的地,并且输入了日期,接下来开始进行预加载。

    当用户点击“开始搜索”后,前端应用就会去判断有没有预加载下级页面(搜索页面)的接口,是否有搜索页的预加载数据,而且这个数据又没有过期,就直接跳转下级页;如果没有可用的预加载数据,此时我们进行一次搜索页的预加载,减少从列表页到搜索页的跳转时间和搜索页的初始化时间。

    预加载是怎么实现的呢?如果 Native 已经提供这个功能,我们直接使用 Native 的预加载接口即可。反之,我们还是需要扩展 Axios 库函数来实现。

    具体来说,在 Axios 进行数据请求后,封装一个 afterFetch 的钩子方法,负责将加载完成的数据存储到本地,供下一个路由使用。这就完成了预加载。当业务侧使用时,先在 aftereFetch 钩子里面定义好取到数据后做什么,然后直接使用 fetch 方法即可。

    比如手机列表页,有一个场景是提前获取下一页的数据做排版,数据预加载完成后,在 afterFetch 里面就会将这些数据存储到内存中。

    需要注意的是,即便是预加载,也要做好缓存处理。 我们要先在内存里面 check 一下是否存在之前预加载的数据。有的话,直接用预加载数据,做后续操作,如果没有,就继续走预加载逻辑,然后设置缓存数据。

    预渲染

    预渲染是指在用户访问这个页面之前,完成页面渲染的准备。还是以机票列表页为例,比如说用户命中特定路径的时候,前端进行判断并会把搜索结果页先渲染出来,只不过在列表页可视区域下方,用户是不可见的。

    当用户点击开始搜索时,前端会去 check,如果已经有了预渲染的页面,只需要把页面显示出来的操作, push 到顶层即可。这样就省去了初始化页面、请求数据和渲染的时间。

    具体怎么实现呢?这就需要用到 “客户端”渲染技术了。你看我在这里加了个引号,其实就是说,它有别于 CSR,而是 NSR(Native side rendering,客户端渲染),即通过客户端(Native 侧)进行页面结构拼接,进而实现页面渲染的处理技术。具体见下图所示。

    Drawing 1.png

    NSR 优化时,需要离线包提供模板等资源(如 HTML、JS、CSS ),预加载提供数据,把页面作为数据经过模板函数变化后产生的结果,然后通过 v8 引擎在客户端渲染出来。

    NSR 是怎么实现的呢?

    首先是模板和数据的准备,用户点击页面链接进入后,这个页面的所有资源是准备好的。具体可以使用前面几讲提到的离线包,以及预请求和预加载方案来做。

    其次,由于页面是动态的而 URL 是静态的,需要实现一种页面与模版的映射机制,一般为多对一,这个机制有助于 Native 快速定位到所需模版。

    最后,在 Native 侧实现一种类似前文 SSR 方案的 Native 本地渲染服务。

    实现完 NSR 之后,业务就可以使用预渲染功能了。在使用时,前端代码不需要做什么改动,业务侧前端工程师接入 NSR,把后置流程准备好就可以了。所谓的后置流程,就是指渲染好下级页面后放置在可视区域之外。

    这里需要注意的一个点是,NSR 是在端内渲染的场景,如果是端外怎么办呢?端外就是纯前端的渲染了,下面以我曾经做过的一个案例和你介绍下。

    当时,公司有个文档内容展现平台,在对文档进行展现时,需要用到虚拟页,即要展示的文档的页码会根据页面内容动态变化,比如在电脑上是展示 1000 字/页,到手机上变成了 120 字/页。这样同一篇文档,在不同平台上显示,需要切割分页,但该操作需要一定的时间。

    所以最好的办法是,当展示第 1 页的时候,就预先渲染第 3 页的内容。具体怎么实现呢?我们是这么做的,在展示第 T 页的时候,在可视范围之外,做 T+2 页的数据切割,切割完进行渲染,渲染完成后放在原地,等点击第 T+2 页时,移动回来。

    预渲染,有时会遇到内存问题,我们可以精简预渲染的内容,比如一些图片资源,可以延后获取。

    小结

    好了,以上就是预请求、预加载及预渲染相关的内容。在实际当中,你可能会遇到预加载和预渲染需要降级的问题,比如没有拿到数据的兜底兼容流程,可以继续使用 CSR,同时如果在端外无法使用离线包,则使用 SSR 是一种很好的替代方案。

    下面为你留一个思考题:

    预请求、预加载和预渲染,你在哪些业务场景中可以用到?

    欢迎在评论区和我交流,下一讲我讲介绍百度、阿里云、美团性能方案对比。


    # 精选评论

    编辑 (opens new window)
    上次更新: 2021/09/20, 16:50:45
    15 高级进阶:WebView 层及代码架构层面优化
    17 横向对比:百度、阿里云、美团性能方案对比

    ← 15 高级进阶:WebView 层及代码架构层面优化 17 横向对比:百度、阿里云、美团性能方案对比→

    最近更新
    01
    好玩的docker
    07-04
    02
    我的第一个NFT
    07-03
    03
    海外迅雷
    06-01
    更多文章>
    Power by vuepress | Copyright © 2015-2023 神族九帝
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式
    ×