交互响应性能之优化FID

因为 FID 须要一个真实用户的交互,因此没法用实验数据测试。html

为了在实验数据下预测 FID,一般会用 TBT(Total Blocking Time),具体这个指标后面文章会介绍。他们测量的内容不一样,但改善 TBT 一般也能改善 FIDvue

一个糟糕的 FID 主要缘由是JS执行过长,优化JS的解析、编译、执行能够直接下降 FIDreact

过长的JS执行

当JS执行过程当中,浏览器没法响应用户交互,由于主线程被占用,为了改善这点,能够:webpack

  • 分解长任务
  • 优化页面,为交互准备
  • 使用 Web Worker
  • 减小JS执行时间

分解长任务

若是你准备尝试减小单个页面的js的体积,能够先考虑把较长执行的js代码分解成小的异步任务。git

长任务指的是用户可能会发现页面无响应的时期执行的js代码。任何阻塞主线程大于等于50ms的代码都是长任务。长任务通常是js体积过大的潜在因素(浏览器加载并执行了比页面初始化所须要的更多的js)。github

分解长任务能够下降用户输入延迟。web

当你采用最佳实践(例如拆分代码、分解长任务),FID 会有显著改善。虽然 TBT 并不是现场数据指标,但这对于改善 FIDTTI(Time To Interactive) 都颇有帮助。浏览器

优化页面,为交互准备

形成 FIDTBT 分数低有不少缘由,大多都是js引发的。babel

本身站点的脚本执行可能会延后交互

  • JS体积过大,执行时间过长,无效的分包会致使页面响应用户交互变慢,影响 FIDTBTTTI。逐步加载代码和功能块能够拆分这些任务,提高响应速度。
  • 服务端渲染看上去页面是出来了,但用户的交互仍是受限于js的执行时间,能够考虑把更多逻辑代码放在服务端实现,或者在构建的时候建立更多静态内容。

下图是 TBT 得分的优化先后对比。经过将非必须的昂贵的脚本的加载和执行移出关键路径,用户就能够更快的去与页面交互。网络

数据获取会影响交互准备的不少方面

  • 级联的获取数据的水流图(包含js,数据的网络请求等),会致使交互延迟。目的是要减小对级联数据获取的依赖。(减小请求数)
  • 较大的内联数据能够节省HTML的解析时间,同时影响绘制图像和交互两种指标。目的是要减小客户端后续处理对数据的依赖。(数据在内联已经准备好了,不须要额外请求)

第三方脚本的执行可能会延后交互

  • 不少网站都包含第三方库的标签和统计代码,这些会致使网络阻塞,使得主线程长时间没法响应,延后了交互。查找出必须加载的第三方代码。(例如:不滚动到指定位置不展现广告)
  • 有时候,第三方的脚本会抢先于本站脚本加载,例如加载优先级和带宽限制。尝试着优先加载你以为能够给用户提供最有价值的东西。

使用 web worker

主线程阻塞是致使输入延迟的主要因素之一。web worker可让你的代码在后台进程中执行,把一些非UI的操做放在web worker中执行能够减小主线程压力,改善 FID 指标。

可使用如下的库,让你的站点更方便的集成web worker:

减小JS执行时间

  • 延后加载未使用的js
  • 最小化无用的polyfill

延后加载未使用的js

经过开发者工具中的coverage的tab页能够查看各资源的有效使用率。

为了减小无用JS,能够:

  • 把你的代码拆分红多个chunk,按需加载
  • 使用 async 或者 defer 延后加载非关键脚本,包含第三方脚本

代码拆分指的是将一个大的单个JS拆分红多个小的,根据条件去加载对应的JS。现代浏览器已经支持按需加载:

import('module.js')    
  .then((module) => {    
    // Do something with the module.    
  });

除了经常使用浏览器支持之外,一些构建系统也支持:

  • webpack,rollup,parcel等构建工具
  • angular,react,vue等客户端框架

除了可使用代码拆分,也可使用 async 或者 defer 来延后加载非关键脚本。

<script defer src="…"></script>    
<script async src="…"></script>

除非有特殊缘由,通常第三方脚本均可以默认采用这种方式加载。

最小化无用的polyfill

若是你用了一些js高级语法,你可能须要将这些代码转换成旧版浏览器支持的语法,或者引入polyfill来支持。

最好的作法是,若是浏览器支持这些语法,不引入polyfill。最小化无用的polyfill,而且将它们的使用限制在须要它们的环境中,能够下降js的体积。

优化polyfill的使用,能够:

  • 若是你是用babel转义,使用 @babel/preset-env 能够只包含你须要支持的浏览器的polyfill。对于babel 7.9,能够开启 bugfixes 配置,进一步减小无用的polyfill。
  • 使用 module/nomodule 的模式传输两份不一样的bundle。(@babel/preset-env 也支持,能够经过 target.esmodules
<script type="module" src="modern.js"></script>    
<script nomodule src="legacy.js" defer></script>

这样能够保证支持js模块的浏览器,能够加载模块化的打包文件,不支持的浏览器能够加载转义后的打包文件。

开发者工具

Lighthouse 6.0 不能测试 FID,由于它是一个现场数据指标,可是 TBT 能够做为替代品测试。针对 TBT 的优化项对 FID 也一样有效。

总结

实际项目的优化须要频繁的使用开发者工具 performance 和 lighthouse。针对长任务进行拆解,针对未使用的js进行移除,针对复杂的js使用web worker。最后再针对旧版浏览器和新版浏览器加载不一样资源,以保证新版浏览器的对polyfill更少的依赖。若是使用webpack打包的项目,能够查看打包的分布图,针对性的去优化每个bundle。

参考

https://web.dev/optimize-fid/

相关文章
相关标签/搜索