乐趣区

关于web:交互响应性能之优化FID

因为 FID 须要一个实在用户的交互,所以无奈用试验数据测试。

为了在试验数据下预测 FID,通常会用 TBT(Total Blocking Time),具体这个指标前面文章会介绍。他们测量的内容不同,但改善 TBT 通常也能改善 FID

一个蹩脚的 FID 次要起因是 JS 执行过长,优化 JS 的解析、编译、执行能够间接升高 FID

过长的 JS 执行

当 JS 执行过程中,浏览器无奈响应用户交互,因为主线程被占用,为了改善这点,能够:

  • 合成长工作
  • 优化页面,为交互筹备
  • 应用 Web Worker
  • 缩小 JS 执行工夫

合成长工作

如果你筹备尝试缩小单个页面的 js 的体积,能够先思考把较长执行的 js 代码分解成小的异步工作。

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

合成长工作能够升高用户输出提早。

当你采纳最佳实际(例如拆分代码、合成长工作),FID 会有显著改善。尽管 TBT 并非现场数据指标,但这对于改善 FIDTTI(Time To Interactive) 都很有帮忙。

优化页面,为交互筹备

造成 FIDTBT 分数低有很多起因,大多都是 js 引起的。

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

  • JS 体积过大,执行工夫过长,有效的分包会导致页面响应用户交互变慢,影响 FIDTBTTTI。逐渐加载代码和功能块能够拆分这些工作,晋升响应速度。
  • 服务端渲染看上去页面是进去了,但用户的交互还是受限于 js 的执行工夫,能够思考把更多逻辑代码放在服务端实现,或者在构建的时候创立更多动态内容。

下图是 TBT 得分的优化前后比照。通过将非必须的低廉的脚本的加载和执行移出要害门路,用户就能够更快的去与页面交互。

数据获取会影响交互筹备的很多方面

  • 级联的获取数据的水流图(蕴含 js,数据的网络申请等),会导致交互提早。目标是要缩小对级联数据获取的依赖。(缩小申请数)
  • 较大的内联数据能够节俭 HTML 的解析工夫,同时影响绘制图像和交互两种指标。目标是要缩小客户端后续解决对数据的依赖。(数据在内联曾经筹备好了,不须要额定申请)

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

  • 很多网站都蕴含第三方库的标签和统计代码,这些会导致网络阻塞,使得主线程长时间无奈响应,延后了交互。查找出必须加载的第三方代码。(例如:不滚动到指定地位不展现广告)
  • 有时候,第三方的脚本会领先于本站脚本加载,例如加载优先级和带宽限度。尝试着优先加载你感觉能够给用户提供最有价值的货色。

应用 web worker

主线程阻塞是导致输出提早的次要因素之一。web worker 能够让你的代码在后盾过程中执行,把一些非 UI 的操作放在 web worker 中执行能够缩小主线程压力,改善 FID 指标。

能够应用以下的库,让你的站点更不便的集成 web worker:

  • Comlink
  • Workway
  • Workerize

缩小 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/

退出移动版