Improving Next.js Performance

Carlos Souza at 2025-03-16

Introduction

Site performance is essential for both SEO and user experience.
In this article, we’ll explore how to optimize a Next.js project to load faster and improve its Google ranking.

Improving Next.js Performance

Reducing Load Time

Lazy Loading can be applied to load only the components and images that are actually needed, reducing the initial load time.

Example of Lazy Loading with Next.js:

import dynamic from "next/dynamic";

const DynamicComponent = dynamic(() => import("../components/HeavyComponent"), { ssr: false });

export default function MyPage() {
  return (
    <div>
      <h1>My Page</h1>
      <DynamicComponent />
    </div>
  );
}

Explanation:

  • dynamic imports the component only when it’s required.
  • { ssr: false } ensures that the component is only loaded on the client side.
  • This reduces the time to first paint (TTFP) and improves overall load speed.

Code Splitting and Bundling

Next.js automatically splits code into smaller bundles, but you can further optimize it by organizing your code more efficiently.

Example of Code Splitting with Dynamic Imports:

const Header = dynamic(() => import('../components/Header'));
const Footer = dynamic(() => import('../components/Footer'));

export default function MyPage() {
  return (
    <div>
      <Header />
      <h1>Welcome to My Page</h1>
      <Footer />
    </div>
  );
}

Best Practices:

  • Use dynamic imports for large components.
  • Keep critical components in the main bundle.
  • Reduce third-party dependencies when possible.

Optimizing Images with next/image

Next.js includes a built-in next/image component that automatically optimizes images for different screen sizes and formats.

Example of next/image usage:

import Image from 'next/image';

export default function MyPage() {
  return (
    <div>
      <Image
        src="/images/example.jpg"
        alt="Example Image"
        width={500}
        height={300}
        layout="responsive"
        priority
      />
    </div>
  );
}

Advantages:

  • Lazy loading is automatically enabled.
  • Images are automatically resized and converted to WebP format.
  • Reduces cumulative layout shift (CLS).

Enabling HTTP/2 and Compression

Enabling HTTP/2 and GZIP/Brotli compression reduces the size of transferred files and improves loading time.

Example of enabling compression in Next.js:

  1. Install the compression package:
npm install compression
  1. Create a custom server (server.js):
const express = require('express');
const next = require('next');
const compression = require('compression');

const app = next({ dev: false });
const handle = app.getRequestHandler();

app.prepare().then(() => {
  const server = express();
  server.use(compression());

  server.all('*', (req, res) => {
    return handle(req, res);
  });

  server.listen(3000, () => {
    console.log('> Ready on http://localhost:3000');
  });
});

Best Practices:

  • Always enable compression for production.
  • Ensure that HTTP/2 is enabled in your hosting configuration.
  • Test using Google PageSpeed Insights.

Minimizing and Caching Static Assets

Minimizing CSS and JavaScript files and using browser caching can significantly improve loading time.

Example of caching static assets with Next.js:

  1. Add caching headers in next.config.js:
module.exports = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'Cache-Control',
            value: 'public, max-age=31536000, immutable',
          },
        ],
      },
    ];
  },
};

Best Practices:

  • Use long-term caching for static files.
  • Minify CSS and JavaScript files before deployment.
  • Test with Lighthouse to identify caching issues.

Conclusion

Improving the performance of your Next.js application involves combining lazy loading, dynamic imports, image optimization, HTTP/2, and effective caching strategies. By following these practices, you can improve your site's loading speed, SEO performance, and user experience.

Key Takeaways:

✅ Use lazy loading for heavy components.
✅ Optimize images with next/image.
✅ Enable HTTP/2 and compression.
✅ Implement code splitting and dynamic imports.
✅ Use long-term caching for static files.

Related Articles