奈飞Web性能优化

2,830

1. 减少javascript的大小

最初的页面(注销状态的首页)包含了300kb的JavaScript,包含了React以及Lodash等库。使用Chrome模拟3G链接,加载时间为7s。

1.png

由于页面是由简单的HTML元素组成的,React不在是必要的,奈飞团队使用原生javascript对页面进行了重构。在删除了React和几个库后,javacript大小减少了200kb以上。缩短了50%的TTI时间。

2.jpeg

使用Lighthouse测试奈飞的主页,TTI时间小于3.5s

3.png

97%的用户的FID的时间也很短

1_Gxkl5liyc-tI7Wh7UTtDlQ.png

📖 名词注解

更多的Web性能指标的说明,我会单独另开一篇文章,这里只提及文章中所提及的

Lighthouse

Lighthouse是开源的提供网页质量的自动化工具,Lighthouse可以通过作为Chrome的扩展程序运行,也可以通过命令行运行。

4.png

点击 Generate report 开始进行测试

5.png

TTI

Time to Interactive, 从页面开始加载开始到其主要的子资源加载完毕之间的时间,优秀的TTI时间应当小于5s。

如何计算TTI?

  1. 从FCP(First Contentful Paint)开始。
  2. 从FCP向后查找是否有5s的静默窗口,静默窗口的定义是: 没有长任务,处于pending中的GET请求不超过2个。
  3. 从静默窗口开始向前查找查找,查找到的第一个长任务的。如果找不到长任务,则到FCP为止。
  4. TTI的时间,是静默窗口向前查找到第一个长任务的结束的时间。如果没有长任务,则是FCP的时间。

下图👇,是上述过程的图解

Long Tasks, 长任务,指的所有执行时间超过50ms的任务

TTI.png

SSR与TTI

SSR技术缩短了网页的FCP时间(因为html已经在服务端渲染好了,只需到客户端水合)。但是SSR可能会导致TTI时间增长,因为FCP的时间被提前了,但是水合还是需要加载一遍javascript文件。我们应当减小FCP与TTI之间的时长,必要时可以明确告知用户资源没有加载完成,避免用户任务页面没有响应。

如何测量TTI

可以使用Lighthouse工具测量

FCP

First Contentful Paint, 从页面开始加载到屏幕上呈现页面内容(任意部分)的时间。内容指:文本,图像,背景图片,svg和非空白的canvas元素。

fcp-filmstrip.png

如何测量FCP?
  1. Chrome用户体验报告
  2. Lighthouse
使用JS测量FCP

最简单的使用方法是使用web-vitals

import { getFCP } from 'web-vitals';

getFCP(console.log);

FID

First Input Delay, 用户第一次与页面进行交互(点击按钮,或者)到浏览器相应交互的时间。优秀FID应当小于100ms。

当浏览器的主线程忙于其他操作时,就会发生"输入延迟"。比如当浏览器在解析执行大型的js文件时,浏览器无法运行任何事件监听器,这个时候如果用户点击按钮,就形成了"输入延迟"。

FID.png

上图中黄色的部分代表的是,主线程正在忙碌的状态。在页面FCP之后,TTI之前(页面看上去好像是可以交互的状态,但是资源尚未加载完成),可能会出现时间较长的“输入延迟”。如果用户在最长的黄色区块附近与页面发生了交互,就会产生较长的FID。

如何测量FID?

可以使用Chrome用户体验报告,或者web-vitals


import { getFID } from 'web-vitals';

getFID(console.log);

2. 预读取React用于后续页面

为了提高下一个页面的性能,我们可以在当前页面预取资源,可以通过两种技术实现。使用 <link rel=prefetch>, 或者XHR预取。

<link rel=prefetch>预取的方式,不能保证浏览器会预取,并且有的浏览器不兼容。

1_TAv9_jZGqmX-aTJw5QDtRA.jpeg

// XHR预取的示例
const xhrRequest = new XMLHttpRequest();
xhrRequest.open'GET''../bundle.js'true);
xhrRequest.send();

通过预取,TTI时间减少了30%

1_yusmoWBbhhfxDEv03OWPTQ.jpeg

其他

  1. Netflix考虑使用Preact(一个类React的库),代替React。对于简单的页面,使用Vanilla JS是更简单的选择
  2. Netflix尝试Service Workers进行静态资源的缓存

原文

参考