A deep dive into Next.js Rendering for Performance and SEO

A deep dive into Next.js Rendering for Performance and SEO

posted 6 min read

Introduction

Hey Everyone, Good to see you back! Rendering in Next.js is a crucial aspect that determines how your web pages are generated and served to users. It can be understood as the process of converting code into user interfaces that users can interact with.

Unlike traditional React applications that rely heavily on Client-Side Rendering (CSR), Next.js pre-renders pages by default, generating HTML in advance, which offers improved performance and SEO benefits.

Types of Rendering in Next.js

Next.js offers several rendering strategies, giving developers the flexibility to choose the best approach for each page or application. The rendering methods available in Next.js include Static Site Generation (SSG), Server-Side Rendering (SSR), Client-Side Rendering (CSR), and Incremental Static Regeneration (ISR).

Static Site Generation (SSG)

ssgimg

This approach creates HTML pages at build time, rather than generating them on demand for each user request. This means that every page of your website is pre-built and stored as static files, and ready to be served instantly when a user accesses the site. The primary benefits of SSG include improved performance, enhanced security, and cost-effectiveness.

Why Use Static Site Generation?

  • Performance: Since the HTML files are pre-generated, they load much faster than dynamically generated pages.
  • Security: Static sites have fewer vulnerabilities because they do not rely on databases or server-side processing.
  • Cost-Effectiveness: Hosting static files is generally cheaper than hosting dynamic sites.
  • Simplicity: Static sites are easier to deploy and maintain.

Implementing SSG

npx create-next-app ssgShowcase
cd ssgShowcase

Followed by:

// pages/index.js
export default function Home({ products }) {
   return (
      <div>
      <h1>SSG showcase</h1>
      <ul>
          {products.map(product => (
          <li key={product.id}>
          <h2>{product.title}</h2>
          <p>{product.description}</p>
          <img src={product.thumbnail} alt={product.title} width="100" />
          </li>
          ))}
      </ul>
      </div>
     );
    }

    export async function getStaticProps() {
    const res = await fetch('https://dummyjson.com/products?limit=10');
    const data = await res.json();
    const products = data.products;

    return {
    props: {
      products,
    },
  };
  }

In this example, we used the getStaticProps function provided by Next.js to fetch data at build time. When you run npm run dev, Next.js will execute this function, fetch the data from the API, and generate static HTML for each product.

Server Side Rendering (SSR)

ssrimg

Server-Side Rendering (SSR) is a rendering technique where the HTML for a web page is generated on the server in response to each request. This means that every time a user requests a page, the server dynamically generates the HTML and sends it to the browser. Unlike Static Site Generation (SSG), where pages are pre-built at build time, SSR ensures the content is always up-to-date. It uses the getServerSideProps function to fetch data on each request, making it ideal for dynamic content that requires real-time updates or personalized data.

Why Use Server-Side Rendering?

  • Dynamic Content: SSR is ideal for applications that display frequently updated or personalized content.
  • SEO for Dynamic Pages: Like SSG, SSR helps with SEO by providing fully rendered HTML to search engine crawlers.
  • Data Fetching at Request Time: SSR allows you to fetch data on each request, ensuring that the content is always current.

Implementing SSR

npx create-next-app ssrShowcase
cd ssrShowcase

Followed by:

  // pages/index.js
  export default function Home({ meal }) {
  return (
    <div>
         <h1>Recipe of the Day</h1>
         <h2>{meal.strMeal}</h2>
         <img src={meal.strMealThumb} alt={meal.strMeal} width="200" />
         <p>Category: {meal.strCategory}</p>
         <p>Instructions: {meal.strInstructions}</p>
    </div>
    );
  }

  export async function getServerSideProps() {
  const res = await fetch('https://www.themealdb.com/api/json/v1/1/random.php');
  const data = await res.json();
  const meal = data.meals[0];

  console.log("Meal Data from API:", meal);
  return {
    props: {
      meal,
    },
   };
  }

Check the terminal or console where you started the Next.js development server. Each time you refresh the page, you'll see the console.log output, including the data fetched from the API and refreshes.

Client Side Rendering (CSR)

csrimg

In this rendering technique, browser renders the web page using JavaScript. It downloads a minimal HTML page along with all the necessary JavaScript. The JavaScript then updates the DOM (Document Object Model) and renders the page. Unlike Server-Side Rendering (SSR) and Static Site Generation (SSG), where the server pre-renders the HTML, CSR generates the content on the client's device.

Why Use Client-Side Rendering?

  • Interactivity: CSR is ideal for highly interactive web applications where the user interface needs to respond quickly to user actions.
  • Dynamic Updates: CSR allows you to fetch and render data on-the-fly, enabling dynamic content updates without refreshing the entire page.
  • Reduced Server Load: With CSR, the server only sends raw data, reducing the load on the server compared to SSR.

Implementing CSR

npx create-next-app csrShowcase
cd csrShowcase

Followed by:

// pages/index.js
import React, { useState, useEffect } from 'react';

export default function Home() {
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);

    useEffect(() => {
       async function fetchData() {
       try {
         const res = await fetch('https://api.quotable.io/random');
         const json = await res.json();
         setData(json);
       } catch (error) {
          setError(error);
       } finally {
             setLoading(false);
       }
     }
    fetchData();
  }, []);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;
  if (!data) return <p>No data</p>;

  return (
     <div>
       <h1>Quote</h1>
       <p>{data.content}</p>
       <p>- {data.author}</p>
     </div>
   );
}

In the above example, we use an important hook called useEffect to fetch data from the Quotable API on the client side. The hook runs after the component has rendered. It fetches the data and updates the component's state, triggering a re-render with the new data. So, When you load the page for the first time, you might notice a slight delay because the page isn't fully rendered until all the JavaScript is downloaded, parsed, and executed. Also, you will see "Loading…" text. Once the data is fetched from the API, the page will be rendered with the quote and author. Refreshing the page will fetch new data and update the content dynamically.

Incremental Site Regeneration (ISR)

isrimg

ISR is a rendering technique in Next.js that allows you to create or update static pages after you've built your application. It enables developers and content editors to use static-generation on a per-page basis, without needing to rebuild the entire application. With ISR, you can retain the benefits of static while scaling to millions of pages. It’s a fairly new way to update static pages and is mainly used for custom built websites.

ISR in Next.js takes the best of static site generation and server-side rendering. Imagine a request comes in for a page, the server first checks if a static version of the page is available. If it exists, the static page is immediately returned. Meanwhile, the server looks at the age of the page. If it's older than a predefined interval, the server will regenerate the page in the background and replace the old one.

ISR uses getStaticProps to fetch data. Add the revalidate property to getStaticProps to use ISR. The revalidate property specifies how often a page should be regenerated. Once this period elapses, the next request to the page triggers a regeneration of the page in the background. While the page is being regenerated, the old version of the page continues to be served to users. Upon completion of the regeneration, the old version of the page is replaced with the new one for subsequent requests. This gives you the flexibility to have constantly updating content on your website without compromising on the advantages of static generation.

Why Use Incremental Static Regeneration?

  • Faster Builds: Reduces build times, especially for large-scale applications.
  • Dynamic Content Updates: Allows for dynamic content updates without sacrificing performance.
  • Scalability: Allows you to retain the benefits of static while scaling to millions of pages.

Implementing ISR

npx create-next-app isrShowcase
cd isrShowcase

Followed by:

// pages/index.js
export async function getStaticProps() {
     const res = await fetch('https://api.quotable.io/random');
     const data = await res.json();

     return {
       props: {
        quote: data.content,
        author: data.author,
     },
      revalidate: 10, // I have added here for every 10 seconds
     };
  }

  export default function Home({ quote, author }) {
     return (
       <div>
         <h1>Random Quote</h1>
         <p>{quote}</p>
         <p>- {author}</p>
       </div>
      );
   }

Conclusion

Next.js offers a versatile suite of rendering techniques, each designed to optimize different aspects of application development. While SSG should generally be the default choice for its superior performance and SEO with static content, SSR becomes essential for highly dynamic content requiring real-time updates, and CSR remains valuable for interactive application. ISR shines in managing large datasets and content updates without full rebuilds. Understanding the strengths and trade-offs of each method allows you to tailor rendering strategies to meet specific project needs, creating applications that are fast, scalable, and optimized.

Thank you for making it to the end! I hope you enjoyed the article, please consider sharing it with someone who might benefit from it.
Feel free to reach out to me on Twitter.

Thankyou Once Again!!

Thankyou

If you read this far, tweet to the author to show them you care. Tweet a Thanks
Nice work it provides a clear and comprehensive breakdown of Next.js rendering methods!  I appreciate how you’ve explained the differences between SSG, SSR, CSR, and ISR with real-world use cases and code examples. Which rendering method do you use most often in your Next.js projects, and why? Have you encountered any challenges when implementing these strategies, and how did you overcome them?

More Posts

Docker Rootless: high security and high performance

jiisanda - Feb 11

ContainerCraft: A Deep Dive into Node.js Containerization

TheToriqul - Jan 30

Titans: A Deep Dive into Next-Generation AI Memory Architecture

Mohit Goyal - Feb 5

Debouncing in JavaScript: A Must-Know Technique for Developers

Mubaraq Yusuf - Feb 15

Modern Use OF Telnet with an example In dotnet,The Rise and Fall of Telnet: A Network Protocol's Journey

Moses Korir - Mar 12
chevron_left