Improve Total Blocking Time in Next.js for Better Lighthouse Scores

NextJS|MAY 28, 2025|0 VIEWS
Actionable strategies to reduce Total Blocking Time and boost your Next.js site's performance

Total Blocking Time (TBT) is a crucial metric in Google Lighthouse and Core Web Vitals. It measures the total time between First Contentful Paint (FCP) and Time to Interactive (TTI) when the main thread is blocked for long enough to prevent input responsiveness. A lower TBT means a more responsive site.

In this article, we'll explore how to improve TBT in a Next.js application.

1. Analyze Your Lighthouse Report

Run a Lighthouse audit (in Chrome DevTools or via PageSpeed Insights) and check the Total Blocking Time metric. Identify which scripts or resources are causing long tasks.

2. Optimize JavaScript Execution

  • Code Splitting: Next.js automatically splits code by page. Use dynamic imports for heavy components:

    import dynamic from "next/dynamic";
    
    const HeavyComponent = dynamic(() => import("../components/HeavyComponent"), {
      ssr: false,
      loading: () => <p>Loading...</p>,
    });
  • Remove Unused Code: Audit your dependencies and remove unused libraries or polyfills.

  • Tree Shaking: Ensure your dependencies support tree shaking. Import only what you need:

    // Instead of importing all of lodash
    import debounce from "lodash/debounce";

3. Reduce Third-Party Scripts

Third-party scripts (analytics, ads, widgets) can block the main thread. Load them asynchronously or defer their loading:

  • Async and Defer: Add async or defer attributes to your <script> tags when including third-party scripts manually.

    <script src="https://example.com/analytics.js" async></script>
  • Use Next.js Script Component: Next.js provides a built-in <Script> component that helps optimize loading strategies for third-party scripts.

    import Script from "next/script";
    
    export default function Page() {
      return (
        <>
          <Script
            src="https://example.com/analytics.js"
            strategy="afterInteractive"
          />
        </>
      );
    }

4. Minimize Long Tasks

Long JavaScript tasks (over 50ms) block the main thread. Break up heavy computations using:

  • Web Workers: Offload expensive computations to a Web Worker.
  • RequestIdleCallback: Schedule non-urgent work during browser idle time.
  • setTimeout / setImmediate: Chunk large tasks into smaller pieces.

5. Optimize Rendering and Styles

  • Critical CSS: Use tools like critical to inline above-the-fold CSS.
  • Avoid Large Layout Shifts: Minimize layout thrashing by reserving space for images and ads.
  • Use CSS Modules or Styled Components: Scope styles to reduce CSS bloat.

6. Monitor and Iterate

Regularly run Lighthouse audits after changes. Use the Web Vitals reporting feature in Next.js to monitor TBT in production.

7. Improve getInitialProps Usage

If you're using getInitialProps in your Next.js pages, be aware that it can increase JavaScript bundle size and block rendering, impacting TBT. Consider these alternatives:

  • Use getStaticProps or getServerSideProps: These methods allow for static generation or server-side rendering, reducing client-side JavaScript execution.

    // pages/blog/[slug].js
    export async function getStaticProps(context) {
      // Fetch data at build time
      return {
        props: {
          // your props here
        },
      };
    }
  • Avoid Heavy Computation in getInitialProps: If you must use getInitialProps, keep logic minimal and avoid heavy synchronous computations.

  • Migrate to Static Generation: Where possible, migrate pages from getInitialProps to static generation for better performance.

For more details, see the Next.js Data Fetching documentation.

8. Server-Side Improvements

Optimizing your server setup can also help reduce TBT by delivering assets faster and reducing main-thread work:

  • Enable Compression: Use gzip or Brotli compression to reduce the size of JavaScript and CSS files sent to the browser.
  • Leverage HTTP/2: Serve your site over HTTP/2 to enable multiplexing and faster asset delivery.
  • Use a CDN: Distribute static assets via a Content Delivery Network to reduce latency and improve load times.
  • Optimize Server Response Times: Ensure your API and server responses are fast by optimizing database queries and server logic.
  • Incremental Static Regeneration (ISR): Use Next.js ISR to serve static pages and update them in the background, reducing server load and improving performance.

These server-side strategies, combined with client-side optimizations, will further enhance your Next.js site's responsiveness and Lighthouse scores.

By following these strategies, you can significantly reduce Total Blocking Time in your Next.js application, leading to better Lighthouse scores and a more responsive user experience.