啥是 LCP
最大内容绘制。
旧指标
- load 和 DOMContentLoaded 不一定和用户看到屏幕对应
- FCP 只能捕捉到加载的最开始
- 过去也推荐 FMP first meaningful paint 和 SI speed index,来获取fp之后的加载性能,但过于复杂(赞同)和容易出错,没办法主要内容合适加载完成。
- 所以简单点,最大块的内容渲染完,基本主体内容就加载完了。
判断条件
和 lcp api 有关。
元素
元素内的
元素(使用海报图像)通过url()函数加载背景图片的元素 (与CSS渐变相反 )包含文本节点或其他内联级文本元素子级的块级元素。
实现方法
最简单的还是加载 库
// 定义变量
let firstHiddenTime = document.visibilityState === 'hidden' ? 0 : Infinity;
// 监听变量
document.addEventListener('visibilitychange', (event) => {
firstHiddenTime = Math.min(firstHiddenTime, event.timeStamp);
}, {once: true});
// send
function sendToAnalytics(data) {
const body = JSON.stringify(data);
// Use `navigator.sendBeacon()` if available, falling back to `fetch()`.
(navigator.sendBeacon && navigator.sendBeacon('/analytics', body)) ||
fetch('/analytics', {body, method: 'POST', keepalive: true});
}
try {
// 创建一个变量
let lcp;
function updateLCP(entry) {
// Only include an LCP entry if the page wasn't hidden prior to
// the entry being dispatched. This typically happens when a page is
// loaded in a background tab.
if (entry.startTime < firstHiddenTime) {
// NOTE: the `startTime` value is a getter that returns the entry's
// `renderTime` value, if available, or its `loadTime` value otherwise.
// The `renderTime` value may not be available if the element is an image
// that's loaded cross-origin without the `Timing-Allow-Origin` header.
lcp = entry.startTime;
}
}
// Create a PerformanceObserver that calls `updateLCP` for each entry.
const po = new PerformanceObserver((entryList, po) => {
entryList.getEntries().forEach((entry) => updateLCP(entry, po));
});
// 监听 largest-contentful-paint
po.observe({
type: 'largest-contentful-paint',
buffered: true,
});
// Log the final LCP score once the
// page's lifecycle state changes to hidden.
addEventListener('visibilitychange', function fn(event) {
if (document.visibilityState === 'hidden') {
removeEventListener('visibilitychange', fn, true);
// Force any pending records to be dispatched and disconnect the observer.
po.takeRecords().forEach((entry) => updateLCP(entry, po));
po.disconnect();
// If LCP is set, report it to an analytics endpoint.
if (lcp) {
sendToAnalytics({lcp});
}
}
}, true);
} catch (e) {
// Do nothing if the browser doesn't support this API.
}
参考资料
- Google 文档 https://web.dev/lcp/
- 知乎系列专栏 页面加载性能之LCP https://zhuanlan.zhihu.com/p/174837488
- 还没自信看的 规范文档 https://wicg.github.io/largest-contentful-paint/