Blazity
Performance Optimization
This article focuses on Web Vitals, Google's standardized way of measuring real user experience on the web.
The Expert Guide to Next.js Performance Optimization
This article is part of The Expert Guide to Next.js Performance Optimization, a comprehensive Ebook you can download for free here.
The guide covers every aspect of building fast, scalable web apps with Next.js, including:
- Streaming, Suspense & Hydration
- Third-Party Scripts
- Font Optimization
- Rendering Strategies
- Core Web Vitals
- Infrastructure
- Real-life Examples
- How to Measure Web Performance
- Bundle Analysis.
This article focuses on Web Vitals, Google's standardized way of measuring real user experience on the web.
You'll learn what the Web Vitals initiative is, why it matters for your site's performance and SEO, and how to interpret Core Web Vitals like LCP, FID, and CLS. We’ll also explain how these metrics help teams speak a common performance language and build faster, more user-friendly websites.
Google's Web Vitals initiative provides a standardized framework for measuring user experience through key performance signals. Web Vitals turns real user metrics into clear, measurable metrics.
This standardization enables site owners to consistently track their performance and understand how users experience their pages. Rather than introducing new optimization techniques, Web Vitals creates a common language and measurement system for evaluating web performance across different sites and contexts.
Core Web Vitals are a subset of Web Vitals, representing the metrics considered most important for user experience. They are part of Google's "Page Experience" signals, which affect a website's search ranking.
The three main metrics of Core Web Vitals are:
LCP (Largest Contentful Paint) measures the time it takes for the largest content element visible in the viewport to become fully loaded and visible to the user. This element could be an image, video, or a sizeable block-level text.
LCP is a key metric for understanding how quickly a page’s main content loads, which is a crucial part of the overall user experience. Pages that load faster engage users better and reduce bounce rates, positively influencing SEO rankings.
Here are some common strategies to optimize Largest Contentful Paint (LCP) in Next.js apps:
next/image
priority prop for above-the-fold images.Use <link rel="preload"> for early fetching essential resources. Evaluate which resources are critical for the first render and preload only those.
Enable server-side rendering to quicken initial content visibility.
Inline necessary above-the-fold CSS.
Establish early connections to crucial third-party domains.
Interaction To Next Paint (INP) is a critical user-centric performance metric used to track a web page's responsiveness. It measures the delay between a user's interaction with a page, such as clicking a link or tapping a button, and the time the browser can begin processing event handlers in response. The INP is essential because it directly impacts the user's perception of the site's interactivity and smoothness.
A lower INP score means a more responsive site, which matters because responsiveness directly impacts user satisfaction. A webpage that reacts swiftly to user inputs feels more fluid and natural, improving the overall user experience.
Taking care of the INP is beneficial for keeping users engaged and also affects the site’s technical optimization. Since search engines prioritize the user experience, a better INP score can contribute positively to a site's search engine optimization (SEO).
Optimizing Interaction to Next Paint (INP) in Next.js is key to making your site feel more responsive and user-friendly. Here are some practical ways to improve it in your app:
Use React 18's selective hydration features to make parts of your page interactive without loading the entire JavaScript bundle. Wrap major components within a <Suspense> boundary to enable non-blocking hydration.
Use lazy loading for images, scripts, and components that aren’t essential to the initial user interaction. Next.js supports automatic image optimization and lazy loading with the <Image> component from next/image.
Code-splitting with dynamic imports helps reduce JavaScript bundle size by loading only what's needed, which lightens the load on the main thread.
Where possible, use CSS instead of JavaScript for animations and transitions. CSS animations are handled by the browser's compositor thread, which can help keep the main thread free for other tasks. This approach optimizes CSS animations for common animation needs like hover effects, transitions between states, or simple movements.
For events that trigger frequently (like scrolling or resizing), implement throttling or debouncing to limit the number of times event handlers are called. Thanks to that, you'll reduce the workload on the main thread.
Simplify the DOM structure and keep it lean. A complex DOM can slow down the page, requiring more computational power to render and re-render UI components.
Offload heavy computations to web workers. It helps to keep the main thread clear for UI and interaction handling, which is critical for maintaining a low INP.
Optimize data fetching strategies using SWR or React Query for efficient data caching and re-fetching, which helps keep the UI responsive.
Use the startTransition API to mark certain updates as non-urgent. This allows React to interrupt these updates if more critical tasks (like handling user inputs) need attention.
CLS (Cumulative Layout Shift) measures a website’s visual stability by tracking unexpected content shifts during loading. A high CLS score can frustrate users, as shifting elements may cause accidental clicks.
Reducing CLS improves stability, enhances user experience, and boosts SEO since Google favors sites with a reliable and consistent layout.
Here are some practical steps you can implement to optimize Cumulative Layout Shift (CLS) in Next.js applications:
Use the Next.js Image component to enforce setting height and width properties, preventing layout shifts caused by image loading.
Implement a consistent layout across all pages using a Layout component to define common structural elements like ad spaces, headers, and menus.
Implement skeleton UIs in the Layout component to maintain layout stability as content loads.
Place ad containers in the Layout component to minimize layout shifts when ads load.
Use font-display settings or preload key fonts to avoid FOUT and layout shifts. Read more about this in chapter 6.2.
Utilize the babel-plugin-styled-components and ServerStyleSheet to apply styles server-side, reducing style recalculations and layout shifts.
Preloading key fonts and critical CSS ensures that the most important resources are loaded as soon as possible, minimizing rendering delays.
Beyond the primary Core Web Vitals, additional metrics help refine web performance analysis. While not officially part of Core Web Vitals, these metrics are essential for developers aiming to deliver a smooth and engaging user experience. They offer a broader view of site performance and help identify areas for improvement.
Let’s take a look at them.
First Contentful Paint (FCP)
First Contentful Paint (FCP) is a key performance metric that measures how quickly a page displays the first piece of content to users during the loading process. It tracks the time from when the navigation to the page starts to when any part of the page's content, such as text or images, is first rendered on the screen.
FCP is important because it signals to users that the page is loading, shaping their perception of the site's speed and responsiveness. Aiming for a fast FCP is essential as it reassures users that the site is responsive. Ideally, sites should achieve an FCP of 1.8 seconds or less to ensure a positive user experience.
Factors influencing FCP include the efficiency of network connections, server speed, and the amount of render-blocking JavaScript, CSS, and fonts.
How to optimize FCP
To improve FCP, you should:
Encapsulate the essential CSS required for rendering above-the-fold content to avoid delaying page render.
Use deferring, async loading, or lazy loading to load non-critical JavaScript after the initial content is rendered, preventing it from blocking the page load.
Implement proper cache control headers and caching policies to store assets locally, reducing load times on repeat visits.
Preload critical fonts and use font-display: swap to ensure text is visible while the fonts are loading, reducing render-blocking.
Total Blocking Time (TBT) measures how long the main thread is blocked by long tasks, preventing the page from responding to user interactions like clicks, taps, or key presses. TBT is measured between First Contentful Paint (FCP) and Time to Interactive (TTI), focusing on the time during which the main thread was blocked long enough to prevent input responsiveness.
TBT is an essential metric for diagnosing user experience issues related to the site's interactivity. It helps identify the “blocking” (longer than 50ms) tasks on the main thread, where the browser cannot process user inputs because it is busy with other tasks.
The metric is highly related to JavaScript execution, as lengthy or inefficient JS tasks can significantly increase the total blocking time, thus degrading the user's interactive experience.
By optimizing JS execution and minimizing complex computations on the main thread, developers can reduce TBT, leading to smoother and more responsive user interaction. The service workers where you could offload some heavy computations would be your ally here.
Time to First Byte (TTFB) is a crucial metric for assessing web server responsiveness and the initial stages of loading performance. It measures the duration from when a resource request is made until the first byte of the response is received.
It contains several phases, including redirect handling, service worker startup, DNS lookups, connection and TLS negotiation, and the initial request processing.
Optimizing TTFB, especially in frameworks like Next.js, starts by ensuring efficient server configurations, reducing DNS lookup times, and streamlining the connection and TLS processes.
Certain metrics have been phased out over time as Web Vitals guidelines evolved. These deprecated metrics are no longer considered best practices.
We’re sharing them here for educational purposes so you can understand what they were and why they’re no longer used. If you’re not interested, feel free to skip this section.
Time To Interactive (TTI)
"Time to Interactive (TTI) has proved overly sensitive to outlier network requests and long tasks, resulting in high variability in this metric. TTI was removed as a metric from Lighthouse 10. Newer, alternative, metrics like Largest Contentful Paint (LCP), Total Blocking Time (TBT), and Interaction to Next Paint (INP) are usually better metrics to use in place of TTI."
First Input Delay (FID)
FID has been a foundational metric for a long time, but it has certain limitations, which we will discuss below. To overcome these challenges, FID has been replaced by Interaction to Next Paint (INP).
Why did INP replace FID?
INP captures the latency of all interactions within a session, making it more representative of the overall user experience. It accounts for interactions after loading the page and continues tracking responsiveness throughout the session.
INP measures how users perceive responsiveness by assessing their visual response to interactions. A better INP results in a smoother experience and higher user satisfaction.
Since INP measures a broader set of interactions, it gives developers more detailed insights into which elements or actions are causing delays. Thanks to that, INP can guide more targeted optimizations.
In the Lighthouse tool, each metric has a specific weight that reflects its importance in the overall performance score. Here's a breakdown of these metrics and their respective weightings, which can help you focus your optimization efforts effectively.
Of course, what you focus on will depend on your priorities and users’ needs, but these weights can serve as general guidance on what metrics matter the most for user experience.
Metric | Abbreviation | Weighting |
---|---|---|
First Contentul Paint | FCP | 10% |
Speed Index (SI) | SI | 10% |
Largest Contentful Paint (LCP) | LCP | 25% |
Total Blocking Time (TBT) | TBT | 30% |
Cumulative Layout Shift (CLS) | CLS | 25% |
Strategic Focus for Optimization
TBT (30%) and LCP (25%) should be your primary focus, given their weightings. Improvements in these areas will have the most significant impact on the overall performance score.
CLS (25%) is also critical due to its high weighting. Ensuring visual stability can significantly enhance user satisfaction.
FCP (10%) and SI (10%) are less weighted but still important. Improvements in these areas contribute to a better initial load experience and progressive content rendering.
Get a quote
“We are very happy with the outcomes and look forward to continuing to work with them on larger initiatives.”
Brian Grafola
CTO at Vibes