Improve NEXTjs performance best practices

Next.js is a framework built on top of React that provides additional features and capabilities to help you build high-performance web applications. While React is a JavaScript library for building user interfaces, Next.js provides a more complete solution for building server-side rendered (SSR) and statically generated (SSG) web applications.

Overall, Next.js is a powerful and flexible framework that can help you build high-performance web applications with ease. It provides many features and capabilities that are not available in React alone, making it a popular choice for building complex, performance-critical web applications.

Here are some of the best practices you can implement to improve your website’s performance:

  1. Server-Side Rendering (SSR)
  2. Code Splitting
  3. Lazy Loading
  4. Minification
  5. Compression
  6. CDN implementation
  7. Image Optimization
  8. Browser Caching
  9. Remove Unused CSS

Server-Side Rendering (SSR)

Next.js has built-in support for SSR, which allows you to render your website on the server before sending it to the browser. This helps to reduce the time it takes for the website to load and improves its overall performance.

To enable SSR in your Next.js website, you can use the getServerSideProps function in your pages. For example:

export async function getServerSideProps() {
  // fetch data from an API or database
  const res = await fetch('https://example.com/data');
  const data = await res.json();

  // return the data as props
  return {
    props: {
      data,
    },
  };
}

function Page({ data }) {
  // render the page using the data
  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.content}</p>
    </div>
  );
}

export default Page;

In this example, we’re fetching data from an API or database using the getServerSideProps function and passing it as props to the Page component. The Page component then renders the data on the page.


Code Splitting

Next.js automatically splits your code into smaller chunks and loads only the necessary code for each page, rather than loading the entire code for your entire website. This reduces the load time and makes your website faster.

To optimize code splitting in your Next.js website, you can use dynamic imports. For example:

import dynamic from 'next/dynamic';

const MyComponent = dynamic(() => import('./MyComponent'));

function Page() {
  // render the MyComponent dynamically
  return <MyComponent />;
}

export default Page;

In this example, we’re using the dynamic function to import the MyComponent component dynamically. This means that the component will only be loaded when it’s needed, reducing the load time of the website.


Lazy Loading

Lazy loading is a concept that we can use to reduce the initial load time of a particular page in web applications.

In a normal scenario when the user initially loads the page all the page content will be loaded, however, sometimes users do not care what’s at the bottom of the page and do not bother to scroll. So loading all content will be in vain.

By using lazy loading we render content on demand of the user, so when the user scrolls down we load the content gradually, not during the initial rendering of the page.

There is a detailed explanation of the implementation is Here


Minification

Minification involves removing unnecessary whitespace, comments, and other characters from your code. This reduces the file size of your website and improves its loading speed.

To minify your Next.js website’s code, you can use a minification tool like uglifyjs-webpack-plugin. For example:

// next.config.js

const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.optimization.minimizer = [
        new UglifyJsPlugin({
          cache: true,
          parallel: true,
          sourceMap: true,
        }),
      ];
    }
    return config;
  },
};

In this example, we’re using the uglifyjs-webpack-plugin to minify our JavaScript code. We’re configuring it to use caching, parallel processing, and source maps for easier debugging. We’re also only applying the minification to client-side code by checking the isServer flag.

You can customize the UglifyJsPlugin configuration as needed based on your specific use case. Additionally, you may want to consider other minification techniques such as minifying your CSS and HTML code as well.


Compression

Compression involves compressing the files on your website before sending them to the browser. This technique helps to reduce the size of your website and improves its loading speed.

here’s an example of how to compress your Next.js assets using the compression-webpack-plugin.

// next.config.js

const CompressionPlugin = require('compression-webpack-plugin');

module.exports = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.plugins.push(
        new CompressionPlugin({
          test: /\.(js|css|html)$/,
          threshold: 10240,
        })
      );
    }
    return config;
  },
};

In this example, we’re using the compression-webpack-plugin to compress our JavaScript, CSS, and HTML assets. We’re configuring it to only compress files larger than 10KB (threshold of 10240 bytes) and to only apply compression to client-side code by checking the isServer flag.

You can customize the CompressionPlugin configuration as needed based on your specific use case. Additionally, you may want to consider other compression techniques such as brotli compression or server-side compression depending on your hosting setup.


CDN uses

A Content Delivery Network (CDN) stores your website’s static assets on multiple servers around the world. This helps to reduce the load time of your website by serving assets from the server closest to the user.

here’s an example of how to use a CDN to serve your Next.js website’s static assets:

// next.config.js

module.exports = {
  // Use a CDN to serve static assets
  assetPrefix: 'https://cdn.example.com/',
};

In this example, we’re setting the assetPrefix configuration option to the URL of our CDN. This tells Next.js to use the CDN URL as the prefix for all static assets (such as images, CSS, and JavaScript files) in our website.

You can customize the CDN URL based on your specific hosting setup. Additionally, you may want to consider using a CDN provider that offers features such as edge caching and global distribution to further optimize the delivery of your website’s static assets.


Image Optimization

Images are often the largest files on a website, and optimizing them can significantly improve your website’s loading speed. You can optimize your images by reducing their file size, compressing them, and using a format that is suitable for the web.

here’s an example that demonstrates the difference between optimizing images using a third-party plugin and using the next/image component:

// Example using third-party plugin for image optimization

// next.config.js

const withOptimizedImages = require('next-optimized-images');

module.exports = withOptimizedImages({
  optimizeImages: true,
  optimizeImagesInDev: false,
});

// MyComponent.js

import Image from 'next/image';

function MyComponent() {
  return (
    <div>
      <img src="/my-image.jpg" alt="My Image" />
      <Image src="/my-image.jpg" alt="My Image" width={1000} height={500} />
    </div>
  );
}

In this example, we’re using the next-optimized-images plugin to optimize images in our Next.js application. We’re also using the next/image component to display an image.

The first image is displayed using a regular img element with the src attribute set to the path of the image file. This image will not be optimized by the next-optimized-images plugin.

The second image is displayed using the next/image component with the src attribute set to the path of the image file and the width and height attributes set to the desired dimensions of the image. This image will be automatically optimized by the sharp library and the next/image component.

By using the next/image component, you can take advantage of built-in image optimization features such as automatic lazy loading, responsive image sizes, and optimized image formats like WebP. Additionally, the next/image component will automatically handle image optimization for you, so you don’t need to use a separate plugin or tool.

However, if you have specific image optimization requirements that are not met by the next/image component, you can use a third-party plugin like next-optimized-images to optimize your images. This gives you more control over how your images are optimized and how they’re delivered to the browser.

Browser Caching

Browser caching involves storing static assets like images, CSS, and JavaScript files in the browser’s cache. This allows the browser to load your website faster when the user revisits it.

here’s an example of how to set up browser caching in your Next.js application using the cache-control HTTP header:

// pages/_app.js

import { useEffect } from 'react';
import { useRouter } from 'next/router';
import { ServerResponse } from 'http';

function MyApp({ Component, pageProps }) {
  const router = useRouter();

  useEffect(() => {
    // Set up browser caching for all pages
    router.beforePopState(({ as }) => {
      if (typeof window !== 'undefined') {
        window.history.replaceState({ as }, '', as);
      }
      return true;
    });

    // Set up browser caching for static assets
    if (typeof window !== 'undefined') {
      const isProd = process.env.NODE_ENV === 'production';
      if (isProd) {
        const addHeaders = (res: ServerResponse) => {
          res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
        };

        addHeaders(window.document);
        const origWrite = document.write;
        document.write = (...args) => {
          addHeaders(document);
          origWrite.apply(null, args);
        };
      }
    }
  }, []);

  return <Component {...pageProps} />;
}

export default MyApp;

In this example, we’re using the cache-control HTTP header to set up browser caching for all pages and static assets in our Next.js application. We’re setting the max-age directive to 31536000 seconds (1 year) to ensure that the browser caches the assets for a long time.

To set up browser caching for all pages, we’re using the router.beforePopState method to intercept the back button and reload the page from the browser cache. This ensures that the page is loaded quickly and efficiently from the cache instead of being reloaded from the server.

To set up browser caching for static assets, we’re using the ServerResponse object to set the Cache-Control header on the response. We’re also intercepting the document.write method to add the Cache-Control header to the HTML document.

By setting up browser caching in this way, you can ensure that your Next.js application loads quickly and efficiently for your users, especially on subsequent visits or when they navigate back to a previous page.


Remove Unused CSS

Removing unused CSS helps to reduce the file size of your website and improve its loading speed. You can use tools like PurgeCSS to remove unused CSS from your website.

here’s an example of how to remove unused CSS in your Next.js application using the purgeCSS library:

// next.config.js

const withPurgeCss = require('next-purgecss');

module.exports = withPurgeCss({
  purgeCssEnabled: ({ dev, isServer }) => !dev && !isServer,
  purgeCssPaths: [
    'pages/**/*.{js,jsx,ts,tsx}',
    'components/**/*.{js,jsx,ts,tsx}',
  ],
});

In this example, we’re using the next-purgecss plugin to remove unused CSS from our Next.js application. We’re configuring the plugin to only run in production mode (not in development mode or on the server) using the purgeCssEnabled option. We’re also specifying the paths to the files that should be analyzed for unused CSS using the purgeCssPaths option.

Once you’ve set up the next-purgecss plugin, you can run a production build of your application using the next build command to generate optimized CSS files.

By removing unused CSS, you can reduce the size of your CSS files and improve the performance of your Next.js application. This can lead to faster page load times, better user experience, and improved SEO.

Leave a Reply

Your email address will not be published. Required fields are marked *