Chrome Devtool Performance 是大家常用的页面性能分析工具,当你使用它来分析页面加载性能的时候会生成如下图所示的报告。
图中包含了以下几个重要的时间点:DCL, L, FP, FCP, FMP, LCP。这里我把前两个和后面几个分开来讲,因为它们分属于不同的W3C标准/草案:navigation timing 和 Paint timing。

DCL, L
DCL(DOMContentLoaded) 表示HTML加载完成事件, L(onLoad) 表示页面所有资源加载完成事件,大家应该对这两个事件非常熟悉了,这里不再多介绍。
不仅是在 performance 报告中,在 Network 面板中也可以查看。

Navigation Timing API
W3C性能工作组在 Navigation Timing API 中定义了一系列页面事件,其中便包括 fetchStart, DOMContentLoaded, Load等事件。
下图展示了从浏览器卸载旧页面到新页面加载完成的整个过程,每个页面事件穿插在每个页面加载阶段之间。


然而 Navigation Timing API 中的 Load 和 DOMContentLoaded 等事件并不能真正的体现页面加载的性能,因为它们并不是与用户在屏幕上看到的相对应。幸运的是,以 Chrome 为首的浏览器提出了其他更能代表用户体验的性能指标。
FP, FCP, FMP, LCP
google工程师一直在推动以用户为中心的性能指标,这些指标旨在回答用户体验的三个问题:
1.发生了吗?
2.它有用吗?
3.它可以使用吗?
发生了吗?-- FP & FCP
当页面开始加载后,用户的第一个重要的体验便是这个。
FP(First Paint): 页面在导航后首次呈现出不同于导航前内容的时间点。
FCP(First Contentful Paint): 首次绘制任何文本,图像,非空白canvas或SVG的时间点。
FP和FCP可能是相同的时间,也可能FP先于FCP。下图展示了 FP 和 FCP 的区别。

这两个事件定义在 W3C Paint Timing 草案中,我们可以通过 window.performance.getEntriesByType('paint') 获取两个时间点的值。

它有用吗 -- FMP & LCP
FMP(First Meaningful Paint): 首次绘制页面“主要内容”的时间点。
FMP是由 Google 工程师引入的一种现代性能指标,它告诉我们页面何时‘有用’。其本质上是通过一种算法来猜测某个时间点可能是FMP。
Chrome目前并没有公开获取 FMP 的 API,只能通过 performance 或者 lighthouse 等性能测试工具查看。

LCP(Largest Contentful Paint): 可视区域“内容”最大的可见元素开始出现在页面上的时间点。
FMP的算法非常复杂,而且并不精确,Google 工程师研究发现了另一种能更精确更简单的测量页面何时“有用”的方法,那就是查看页面何时渲染最大的元素。

// Create a variable to hold the latest LCP value (since it can change).
let lcp;
// Create the PerformanceObserver instance.
const po = new PerformanceObserver((entryList) => {
const entries = entryList.getEntries();
const lastEntry = entries[entries.length - 1];
// Update `lcp` to the latest value, using `renderTime` if it's available,
// otherwise using `loadTime`. (Note: `renderTime` may not be available if
// the element is an image and it's loaded cross-origin without the
// `Timing-Allow-Origin` header.)
lcp = lastEntry.renderTime || lastEntry.loadTime;
});
// Observe entries of type `largest-contentful-paint`, including buffered
// entries, i.e. entries that occurred before calling `observe()`.
po.observe({type: 'largest-contentful-paint', buffered: true});
// Send the latest LCP value to your analytics server once the user
// leaves the tab.
addEventListener('visibilitychange', function fn() {
if (lcp && document.visibilityState === 'hidden') {
console.log('LCP:', lcp);
removeEventListener('visibilitychange', fn, true);
}
}, true);
用户体验的第三个问题“可以使用吗”可以用 TTI(Time to Interactive) 查看,它表示你的页面何时可以自由响应用户交互。它和 FMP 一样还不是 W3C 规范,也没有获取它的标准的 API,但 Google 提供了一个 TTI 的 polyfill 可以用来检测,你也可以用 lighthouse 获取 TTI。
新的性能指标
在今年11月举行的 Chrome Developer Summit 上,W3C 性能工作组介绍了他们正在研究的三个性能指标:LCP, CLS 和 TBT。
CLS(Cumulative Layout Shift): 表示用户经历的意外 layout 偏移的频率。
TBT(Total Blocking Time): 表示从 FCP 到 TTI 之间,所有 long task 的阻塞时间之和。
新的 Lighthouse 性能得分将很快不再强调 FMP 和 FCI,并将包含 LCP, TBT, CLS 三个新特性。
