Skip to content

Commit 3fdf0e9

Browse files
committed
Updated LCP code snippets to start measuring from activation
1 parent 92e7073 commit 3fdf0e9

File tree

2 files changed

+59
-13
lines changed

2 files changed

+59
-13
lines changed

pages/CoreWebVitals/LCP-Sub-Parts.mdx

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
### Largest Contentful Paint Sub-Parts (LCP)
22

3-
This script is part of the [Web Vitals Chrome Extension](https://chrome.google.com/webstore/detail/web-vitals/ahfhijdlegdabablpippeagghigmibma) and appear on the [Optimize Largest Contentful Paint](https://web.dev/i18n/en/optimize-lcp/) post.
3+
This script is part of the [Web Vitals Chrome Extension](https://chrome.google.com/webstore/detail/web-vitals/ahfhijdlegdabablpippeagghigmibma) and appear on the [Optimize Largest Contentful Paint](https://web.dev/articles/optimize-lcp) post.
44

55

66
#### Snippet
@@ -15,27 +15,33 @@ const LCP_SUB_PARTS = [
1515

1616
new PerformanceObserver((list) => {
1717
const lcpEntry = list.getEntries().at(-1);
18-
const navEntry = performance.getEntriesByType("navigation")[0];
18+
const navEntry = getNavigationEntry();
1919
const lcpResEntry = performance
2020
.getEntriesByType("resource")
2121
.filter((e) => e.name === lcpEntry.url)[0];
2222

23-
const ttfb = navEntry.responseStart;
23+
const activationStart = getActivationStart()
24+
25+
const ttfb = Math.max(0, navEntry.responseStart - activationStart);
2426
const lcpRequestStart = Math.max(
25-
ttfb,
26-
lcpResEntry ? lcpResEntry.requestStart || lcpResEntry.startTime : 0,
27+
ttfb,
28+
// Prefer `requestStart` (if TOA is set), otherwise use `startTime`.
29+
lcpResEntry
30+
? (lcpResEntry.requestStart || lcpResEntry.startTime) -
31+
activationStart
32+
: 0,
2733
);
2834
const lcpResponseEnd = Math.max(
2935
lcpRequestStart,
30-
lcpResEntry ? lcpResEntry.responseEnd : 0,
36+
lcpResEntry ? lcpResEntry.responseEnd - activationStart : 0,
3137
);
3238
const lcpRenderTime = Math.max(
3339
lcpResponseEnd,
34-
lcpEntry ? lcpEntry.startTime : 0,
40+
lcpEntry.startTime - activationStart,
3541
);
36-
42+
3743
LCP_SUB_PARTS.forEach((part) => performance.clearMeasures(part));
38-
44+
3945
const lcpSubPartMeasures = [
4046
performance.measure(LCP_SUB_PARTS[0], {
4147
start: 0,
@@ -54,7 +60,7 @@ new PerformanceObserver((list) => {
5460
end: lcpRenderTime,
5561
}),
5662
];
57-
63+
5864
// Log helpful debug information to the console.
5965
console.log("LCP value: ", lcpRenderTime);
6066
console.log("LCP element: ", lcpEntry.element, lcpEntry?.url);
@@ -63,9 +69,29 @@ new PerformanceObserver((list) => {
6369
"LCP sub-part": measure.name,
6470
"Time (ms)": measure.duration,
6571
"% of LCP": `${
66-
Math.round((1000 * measure.duration) / lcpRenderTime) / 10
72+
Math.round(((1000 * measure.duration) / lcpRenderTime) || 0) / 10
6773
}%`,
6874
})),
6975
);
7076
}).observe({ type: "largest-contentful-paint", buffered: true });
77+
78+
function getActivationStart() {
79+
const navEntry = getNavigationEntry();
80+
return (navEntry && navEntry.activationStart) || 0;
81+
}
82+
83+
function getNavigationEntry() {
84+
const navigationEntry =
85+
self.performance &&
86+
performance.getEntriesByType &&
87+
performance.getEntriesByType('navigation')[0];
88+
89+
if (
90+
navigationEntry &&
91+
navigationEntry.responseStart > 0 &&
92+
navigationEntry.responseStart < performance.now()
93+
) {
94+
return navigationEntry;
95+
}
96+
}
7197
```

pages/CoreWebVitals/LCP.mdx

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,38 @@ const po = new PerformanceObserver((list) => {
1919
entries.forEach((item, i) => {
2020
console.dir(item);
2121
console.log(
22-
`${i + 1} current LCP item : ${item.element}: ${item.startTime}`,
22+
`${i + 1} current LCP item : ${item.element}: ${Math.max(item.startTime - getActivationStart(), 0)}`,
2323
);
2424
item.element ? (item.element.style = "border: 5px dotted lime;") : "";
2525
});
2626

2727
const lastEntry = entries[entries.length - 1];
28-
console.log(`LCP is: ${lastEntry.startTime}`);
28+
console.log(`LCP is: ${Math.max(lastEntry.startTime - getActivationStart(), 0)}`);
2929
});
3030

3131
po.observe({ type: "largest-contentful-paint", buffered: true });
3232

3333
function dedupe(arr, key) {
3434
return [...new Map(arr.map((item) => [item[key], item])).values()];
3535
}
36+
37+
function getActivationStart() {
38+
const navEntry = getNavigationEntry();
39+
return (navEntry && navEntry.activationStart) || 0;
40+
}
41+
42+
function getNavigationEntry() {
43+
const navigationEntry =
44+
self.performance &&
45+
performance.getEntriesByType &&
46+
performance.getEntriesByType('navigation')[0];
47+
48+
if (
49+
navigationEntry &&
50+
navigationEntry.responseStart > 0 &&
51+
navigationEntry.responseStart < performance.now()
52+
) {
53+
return navigationEntry;
54+
}
55+
}
3656
```

0 commit comments

Comments
 (0)