Next.js: The Ultimate Cheat Sheet To Page Rendering

Next.js uses 4 rendering strategies to build, deliver and render a React Single Page App (SPA):

1. Static-Site Generation (SSG)
2. Server-Side Rendering (SSR)
3. Incremental Static Regeneration (ISR)
4. Client-Side Rendering (CSR)

This is the easiest and most complete cheat sheet to quickly understand how Next.js page rendering strategies works. Moreover, this unique cheat sheet clearly reveals how each strategy influences the Core Web Vitals signals: TTFB, FP, FCP, LCP, TBT and TTI.

Detailed explanations are also included to help you choose the right page rendering strategy for all use cases and thus create speedy Web applications that Google and visitors love.

P.S.: Thanks in advance for including this cheat sheet in your blog articles and mentioning the author with a link back to this cheat sheet like this: Next.js: The Ultimate Cheat Sheet To Page Rendering.

Enjoy!

 

How to use

The 4 page rendering strategies are identified with their respective acronym (SSG, SSR, ISR and CSR) and laid out in columns besides each other in the middle of the infographic.

Completely on the left side of these 4 columns you’ll find the 6 steps involved during the processing flow from the build step on the server side up to the client-side rendering.

Completely on the right side of these 4 columns you’ll find where each step happens in the processing flow which is either server side or client side.

For each strategy column you’ll see where and when a build action (page generation) is executed in the step. You’ll also see the generated content flow (HTML - React/CSS/JS/Data) during each single step.

Core Web Vitals

The Core Web Vitals (CWV), parts of the new page experience ranking factor from Google, are identified using 3 distinctive background colors, each related to the performance impact on the CWV.

A red color means POOR performance results, an orange color means GOOD performance while a green color means the BEST performance.

Live Demo

You’ll find a live demo with example source code on Github for testing the performance of each page rendering strategies discussed in the cheat sheet:
https://next-page-rendering.vercel.app/

 

Static-Site Generation (SSG)

Static-Site Generation (SSG) is the default strategy offered by Next.js to generate web pages. Next.js recommends this strategy to get the best performance results as static content is distributed faster using CDNs which are closer to your visitors and thus leading to a faster Time to First Byte (TTFB).

Steps description

STEP 1: Next.js generates a Single Page App in an .html file along with the .css and .js on the server. This step called pre-rendering is done only once at build time when you run the next build command. That is usually done when you deploy your application. This is during this step that all the page coding (HTML) is generated including the React code, CSS, JavaScript and optionally the data if the page is using any data fetching method such as getStaticProps() or getStaticPaths().

STEP 2: The client requests the Single Page App from the CDN.

STEP 3: The client downloads the Single Page App from the CDN.

STEP 4: The client parses and renders the Single Page App into the browser. This is where the 3 Core Web Vitals signals (First Paint, First Contentful Paint and Largest Contentful Paint) are fired. Because the HTML of the page has been pre-rendered on the server side, the client browser just has to load and render it as is. And because the page is coded in a way that allows the browser to render it with minimum JavaScript code, render-blocking is reduced to its minimum leading to good performance results.

STEP 5: The React (JavaScript) code is run to (re)Hydrate the page. Even though the page has been pre-built, this extra step is required to allow React to attach or activate the JavaScript events to its Virtual DOM and make the page interactive. Because JavaScript is run at this point, Total Blocking Time is affected by this extra step. Also, because the browser has to wait for the hydration process to complete, Time To Interactive is also affected.

Here is the complete Typescript code of a web page that uses Next.js' Static-Site Generation strategy (SSG):

// Next.js libraries
import Head from 'next/head'

// Custom Components
import BackToHome from 'components/BackToHome'

// Page component
export default function StaticSideGeneration({ jsonData }) {
  return (
    <>
      <Head>
        <title>Static-Site Generation (SSG) • Guy Dumais</title>
        <meta name="description" content="Example page using Static-Site Generation (SSG) with Next.js 11 and React 17"/>
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
      </Head>
      <BackToHome/>
      <h1>Static-Site Generation (SSG)</h1>
      <p>Data fetched at build-time on the server-side before sending to the client.</p>
      <ul>
      {
        jsonData.data.map((e) => (
          <li key={e.id}>{e.email}</li>
        ))
      }
      </ul>
    </>
  )
}

// This function gets called at build time on server-side.
// It won't be called on client-side, so you can even do
// direct database queries.
export async function getStaticProps() {
  const res = await fetch('https://reqres.in/api/users?page=2')
  const jsonData = await res.json()

  return {
    props: {
      jsonData, // will be passed to the page component as props
    },
  }
}

 

Server Side Rendering (SSR)

Server Side Rendering (SSR) is the second strategy offered by Next.js to generate web pages. Next.js recommends to avoid using this strategy as much as possible to get the best performance results as the static content is built (pre-rendered) and distributed per-request only. Because of the extra time required by the build process, the Time to First Byte (TTFB) signal is increased and leads to poor results.

Steps description

STEP 1: Next.js does not generate (pre-render) any page.

STEP 2: The client requests the Single Page App from the server. Next.js generates (pre-render) a Single Page App in an .html file along with the .css and .js on the server. This is during this step that all the page coding (HTML) is generated including the React code, CSS, JavaScript and optionally the data if the page is using the getServerSideProps() data fetching method.

STEP 3: The client downloads the Single Page App from the server.

STEP 4: Same as STEP 4 in SSG.

STEP 5: Same as STEP 5 in SSG.

Here is the complete Typescript code of a web page that uses Next.js' Server Side Rendering strategy (SSR):

// Next.js libraries
import Head from 'next/head'

// Custom Components
import BackToHome from 'components/BackToHome'

// Page component
export default function ServerSideRendering({ jsonData }) {
  return (
    <>
      <Head>
        <title>Server-Side Rendering (SSR) • Guy Dumais</title>
        <meta name="description" content="Example page using Server-Side Rendering (SSR) with Next.js 11 and React 17"/>
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
      </Head>
      <BackToHome/>
      <h1>Server-Side Rendering (SSR)</h1>
      <p>Data fetched on the server-side at <b>each</b> request before sending to the client.</p>
      <ul>
      {
        jsonData.data.map((e) => (
          <li key={e.id}>{e.email}</li>
        ))
      }
      </ul>
    </>
  )
}

export async function getServerSideProps() {
  const res = await fetch('https://reqres.in/api/users?page=2')
  const jsonData = await res.json()

  return {
    props: {
      jsonData, // will be passed to the page component as props
    },
  }
}

 

Incremental Static Regeneration (ISR)

Incremental Static Regeneration (ISR) is the third strategy offered by Next.js to generate web pages. It is the same as Static Site Generation except that content can be rebuilt when the page is updated.

Steps description

STEP 1: Same as STEP 1 in SSG.

STEP 2: The client requests the Single Page App from the CDN. Also, if the page is using the data fetching method getStaticProps() combined with the revalidate option, then the page is regenerated if the data returned from the fetching results has been updated. Next.js recommends using this method for a huge site having over 1,000 pages. Because pre-rendering each page takes time, using this incremental method will pre-render on the first request and when the page content is updated only.

STEP 3: Same as STEP 3 in SSG.

STEP 4: Same as STEP 4 in SSG.

STEP 5: Same as STEP 5 in SSG.

Here is the complete Typescript code of a web page that uses Next.js' Incremental Static Regeneration strategy (ISR):

// Next.js libraries
import Head from 'next/head'

// Custom Components
import BackToHome from 'components/BackToHome'

// Page component
export default function IncrementalStaticGeneration({ jsonData }) {
  return (
    <>
      <Head>
        <title>Incremental Static Regeneration (ISR) • Guy Dumais</title>
        <meta name="description" content="Example page using Incremental Static Regeneration (ISR) with Next.js 11 and React 17"/>
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
      </Head>
      <BackToHome/>
      <h1>Incremental Static Regeneration (ISR)</h1>
      <p>Data fetched at build-time on the server-side and rebuilt when data updated.</p>
      <ul>
      {
        jsonData.data.map((e) => (
        <li key={e.id}>{e.email}</li>
      ))
      }
      </ul>
    </>
  )
}

// This function gets called at build time on server-side.
// It may be called again, on a serverless function, if
// revalidation is enabled and a new request comes in
export async function getStaticProps() {
  const res = await fetch('https://reqres.in/api/users?page=2')
  const jsonData = await res.json()

  return {
    props: {
      jsonData, // will be passed to the page component as props
    },

    // Next.js will attempt to re-generate the page:
    // - When a request comes in
    // - At most once every second
    revalidate: 100, // In seconds
  }
}

 

Client Side Rendering (CSR)

Client Side Rendering (CSR) is the fourth strategy offered by Next.js to generate web pages. It is the same as Static Site Generation except that parts of the content can be built on the client side.

Steps description

STEP 1: Same as STEP 1 in SSG except that the content (data) is not pre-rendered nor included in the static bunch. Which results in a smaller file size thus leading to shorter download time.

STEP 2: Same as STEP 2 in SSG but without content (data).

STEP 3: Same as STEP 3 in SSG but without content (data).

STEP 4: Same as STEP 4 in SSG.

STEP 5: Same as STEP 5 in SSG but without content (data).

STEP 6: The client fetches the content (data) and React updates the UI. This method is useful, for example, when you want to show up a skeleton page with static content and then progressively inject the data in a page requiring a long wait time for data fetching.

// React
import { useEffect, useState } from 'react'

// Next.js
import Head from 'next/head'
import Link from 'next/link'

// Custom Components
import BackToHome from 'components/BackToHome'

// Page component
export default function ClientSideRendered() {

  const [state, setState] = useState([] as any)

  const getData = async () => {
    const res = await fetch('https://reqres.in/api/users?page=2')
    const jsonData = await res.json()
    setState(jsonData)
  }

  useEffect(() => {
    getData()
  }, [])

  return (
    <>
      <Head>
        <title>Client-Side Rendering (CSR) • Guy Dumais</title>
        <meta name="description" content="Example page using Client-Side Rendering (CSR) with Next.js 11 and React 17"/>
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
      </Head>
      <BackToHome/>
      <h1>Client-Side Rendering (CSR)</h1>
      <p>Data fetched on the client-side only.</p>
      <ul>
      {
        state.data?.map((e) => (
          <li key={e.id}>{e.email}</li>
        ))
      }
      </ul>
    </>
  )

}

126