Optimize Core Web Vitals with Lighthouse and DevTools
February 20, 2021
Today, we’ll cover some of the tools the Lighthouse & DevTools teams in Chrome worked on to help identify how your site can improve on the Core Web Vitals.
As a refresher on the tools, Lighthouse is an open-source, automated tool for improving the quality of web pages. You can find it in the Chrome DevTools suite of debugging tools and run it against any web page, public or requiring authentication. You can also find Lighthouse in PageSpeed Insights, CI and WebPageTest.
Measure Core Web Vitals
Lighthouse can measure the 2020 Core Web Vitals metrics including Largest Contentful Paint, Cumulative Layout Shift and Total Blocking Time (a lab proxy for First Input Delay). These metrics reflect loading, layout stability and interaction readiness. We will of course be keeping an eye on future CWV metrics too.
The “Metrics” section of the Lighthouse report includes lab versions of these metrics. You can use this as a summary view of what aspects of user-experience require your attention.
The new Web Vitals option in the DevTools Performance panel displays a track which highlights metric moments, such as Layout Shift (LS) shown above.
Field metrics, such as those found in the Chrome UX Report or RUM, do not have this limitation and are a valuable complement to lab data as they reflect the experience real users have. Field data can’t offer the kinds of diagnostic information you get in the lab, so the two go together hand in hand.
Several third-party services offer dashboards for field and RUM data, including SpeedCurve (LUX), Vercel Analytics, Akamai mPulse and Treo.sh.
Identify where you can improve on CWV
Identify the Largest Contentful Paint element
LCP is a measurement of perceived loading experience. It marks the point during page load when the primary–or “largest”–content has loaded and is visible to the user.
Lighthouse has a “Largest Contentful Paint element” audit that identifies what element was the largest contentful paint. Hovering over the element will highlight it in the main browser window.
If this element is an image, this information is a useful hint you may want to optimize the loading of this image. Lighthouse includes a number of image optimization audits for helping you understand if your images could be better compressed, resized or delivered in a more optimal modern image format.
You might also find this helpful LCP Bookmarklet by Annie Sullivan useful for quickly identifying the LCP element with a red rectangle in just one click.
Preload late-discovered images to improve LCP
To improve the Largest Contentful Paint, preload your critical hero images if they are being discovered late by the browser. This can happen if a JavaScript bundle needs to be loaded before the image is discoverable.
Lighthouse now suggests opportunities to apply this optimization in Lighthouse 6.5 and above. There are a few common questions we are asked about preloading LCP images that may also be worth briefly covering.
Can you preload responsive images? Yes. Let’s say we have a responsive hero image as specified using srcset
and sizes
below:
<img src="lighthouse.jpg"
srcset="lighthouse_400px.jpg 400w,
lighthouse_800px.jpg 800w,
lighthouse_1600px.jpg 1600w" sizes="50vw" alt="A helpful Lighthouse">
Thanks to the imagesrcset
and imagesizes
attributes added to the link
attribute, we can preload a responsive image using the same image selection logic used by srcset
and sizes
:
<link rel="preload" as="image" href="lighthouse.jpg"
imagesrcset="lighthouse_400px.jpg 400w,
lighthouse_800px.jpg 800w,
lighthouse_1600px.jpg 1600w" imagesizes="50vw">
Will the audit also highlight preload opportunities if the LCP image is defined via a CSS background? Yes.
Any image flagged as the LCP image whether via CSS background or <img>
is a candidate if it’s discovered at a waterfall depth of 3 or more.
Identify CLS contributions
Cumulative Layout Shift is a measurement of visual stability. It quantifies how much a page’s content visually shifts around. Lighthouse has an audit for debugging CLS called “Avoid large layout shifts”.
This audit highlights DOM elements that contribute the most to shifts of the page. In the Element column to the left you will see the list of these DOM elements and to the right, their overall CLS contribution.
For post-load CLS, I personally find a lot of value in persistently visualizing with rectangles which elements contributed the most to CLS. This is a feature you’ll find in third-party tools like SpeedCurve’s Core Web Vitals dashboard and which I love using Defaced’s Layout Shift GIF Generator for:
For a site-wide view of layout shift issues, I get a lot of mileage out of Search Console’s Core Web Vitals report. This lets me see the kinds of pages on my site with a high CLS (in this case helping self-identify what template partials I need to spend my time on):
Identifying CLS from images without dimensions
To limit Cumulative Layout Shift being caused by images without dimensions, include width and height size attributes on your images and video elements. This approach ensures that the browser can allocate the correct amount of space in the document while the image is loading.
See Setting Height And Width On Images Is Important Again for a good write-up on the importance of thinking about image dimensions and aspect ratio.
Identifying CLS from advertisements
Publisher Ads for Lighthouse allows you to find opportunities to improve the loading and user-experience of ads on your page, including contributions to layout shift and long tasks that may push out how soon your page is usable by users. In Lighthouse, you can enable this via Community Plugins.
Avoid non-composited animations
Animations which are non-composited can present themselves as janky on lower-end devices if heavy JavaScript tasks are keeping the main thread busy. Such animations can introduce layout shifts.
If Chrome discovers an animation couldn’t be composited, it reports it to a DevTools trace Lighthouse reads, allowing it to list which elements with animations weren’t composited and for what reason. You can find these in the “Avoid non-composited animations” audit.
Debug First Input Delay / Total Blocking Time / Long Tasks
First Input measures the time from when a user first interacts with a page (i.e. when they click a link, tap on a button, or use a custom, JavaScript-powered control) to the time when the browser is actually able to begin processing event handlers in response to that interaction. Long JavaScript Tasks can impact this metric and the proxy for this metric, Total Blocking Time.
Lighthouse includes an “Avoid long main-thread tasks” audit which lists the longest tasks on the main thread. This can be helpful for identifying the worst contributors to input delay. In the left column we can see the URL of scripts responsible for long main-thread tasks.
To the right we can see the duration of these tasks. As a reminder, Long Tasks are tasks which execute for longer than 50 milliseconds. This is considered to block the main thread long enough to impact frame rate or input latency.
If considering third-party services for monitoring, I also quite like the main-thread execution timeline visual Calibre has for visualizing these costs, which highlights both parent and child tasks contributing to long tasks that impact interactivity.
Block network requests to see the before/after impact in Lighthouse
Chrome DevTools supports blocking network requests to see the impact of individual resources being removed or not being available. This can be helpful for understanding the cost individual scripts (e.g such as third-party embeds or trackers) have on metrics like Total Blocking Time (TBT) and Time to Interactive.
Network request blocking happens to also work with Lighthouse! Let’s take a quick look at the Lighthouse report for a site. The Perf score is 63/100 with a TBT of 400ms. Digging into the code, we find this site loads an Intersection Observer polyfill in Chrome which isn’t necessary. Let’s block it!
We can right-click on a script in the DevTools Network panel and click ‘Block Request URL’ to block it. Here we’ll do this for the Intersection Observer polyfill:
Next we can re-run Lighthouse. This time we can see our performance score has improved (70/100) as has Total Blocking Time (400ms => 300ms).
Replace costly third-party embeds with a facade
It’s common to use third-party resources for embedding videos, social media posts or widgets into pages. By default, most embeds eagerly load right away and can come with costly payloads that negatively impact the user-experience. This is wasteful if the third-party isn’t critical (e.g if the user needs to scroll before they see it).
One pattern to improve performance of such widgets is to lazy-load them on user interaction. This can be done by rendering a lightweight “preview” of the widget (a facade) and only load the full version if a user interacts with it. Lighthouse has an audit that will recommend third-party resources which can be lazy-loaded with a facade, such as YouTube video embeds.
Beyond Core Web Vitals
Beyond highlighting the Core Web Vitals, recent versions of Lighthouse also try to provide concrete guidance you can follow for improving how quickly JavaScript-heavy web applications can load.
These include audits for a growing collection of audits for reducing the cost of JavaScript in your page, such as reducing reliance on polyfills and duplicates that may not be needed for the user-experience.
For more information, keep an eye on the Lighthouse team Twitter account What’s new in DevTools.
With thanks to Demian Renzulli and Elizabeth Sweeny for their reviews.