Pre-rendering in Next.js

Background Image by Gradienta on Unsplash

What is pre-rendering?

Pre-rendering means generating HTML for each page in advance, together with minimal javascript code needed for that page.

After the page gets loaded into the browser, Javascript code gets executed and makes the page fully interactive. This part of the process is known as hydration.

Why pre-render?

  1. Pre-rendering improves performance
  • In a typical react app, you need to wait until the javascript code gets loaded into the browser and gets executed. Because of that, it will take some more time to render the UI
  • With a pre-rendered page, the HTML is already generated and loads faster

2. Pre-rendering helps with SEO

  • If you are building a blog or e-commerce site, SEO is a concern.
  • If you examine the source code of a web app created using CRA(create-react-app), you will only see a div tag with id equal to root in its body. That’s because its content is getting rendered using client-side rendering. If a search engine hits a such page, the search engine won’t be able to see the content. Because of that, a typical react app created using CRA, is not SEO friendly.
  • If the search engine hits a pre-rendered page that is created using Next.js, all the content is present in the source code which will help to index that page.

A test to check pre-rendering in an existing website

Let’s do a small test to check whether a given website is configured with pre-rendering.

  1. First, visit both of those pages and see if they are working.
  2. Now you have to disable javascript in your browser. Pick the relevant guide for the browser that you are using, to disable javascript
    Chrome/Brave Guide
    Firefox Guide
    Safari Guide
  3. After disabling javascript, you have to visit those two sites again using the same browser tab (which you disabled javascript) to check whether they are working.
    You’ll notice that Shu’s page is working fine and the CRA page is showing a message saying that ‘You need to enable JavaScript to run this app.’ You are seeing this message because the app is not pre-rendered into static HTML.
  • On Shu’s page, a pre-rendered HTML will be displayed during the initial load. After that, the javascript code gets loaded into the browser and then the app becomes interactive (This process is known as hydration).
  • On CRA page, there’s nothing during the initial load because the javascript is not getting loaded during the initial load. Once the browser loads the javascript code, the whole page gets rendered and becomes interactive.

Forms of Pre-rendering

There are two forms of pre-rendering in Next.js.

  1. Static Generation
  2. Server-side rendering

We can configure a page of a Next.js app to pre-render in either one of these forms. But ‘Static Generation’ is the form that is recommended by Next.js Team.

Static Generation

A page that uses Static Generation as its pre-rendering form, generates its HTML during the build time.
In production, This process takes place only when you run next build command. But in development mode (when you run npm run dev), pages will get pre-rendered on every request.

The HTML that gets generated using this process can be reused on each request and also it can be cached by a CDN.

Static Generation will automatically happen when there’s no data that component needs to be fetched from an external source (External API, querying the database etc.)

But if you have to fetch some data from an external source, you will have to use getStaticProps function to fetch those data.

Static generation is advised to be used if the data in your page are not getting changed frequently (For example, blog posts, marketing pages, e-commerce product listing, help and documentation, etc.)

Below is a code of a Next.js component where it fetches a list of users from a free API. Here we have used getStaticProps to fetch data.

// pages/sg/index.js

import styles from "../../styles/Home.module.css";
import Link from "next/link";

export default function Component({ users }) {
return (
<>
<main className={styles.main}>
<h1>Static Generation</h1>
<div className={styles.description}>
<ul>
{users.map((user) => (
<li key={user.email}><Link href={`/sg/${user.id}`}>{user.name}</Link></li>
))}
</ul>
</div>
</main>
</>
);
}

// this function gets called during the build time
export async function getStaticProps() {
// calling an external API to fetch data
const res = await fetch("https://jsonplaceholder.typicode.com/users");
const users = await res.json();

// this returning data can be accessed from the component using the prop name
return { props: { users } };
}

Below is the output of that code.

Output of Static Generation Code

This guide will give you more information about getStaticProps

If you want to route to a specific page (which contains more details about that specific user) when you click on a name in that list of users above, you can call getStaticPaths() function from a dynamic page.

// pages/sg/[id].js

import styles from "../../styles/Home.module.css";

const Post = ({ user }) => {
console.log("user", user);

return (
<>
<main className={styles.main}>
<h1>Static Generation (Paths)</h1>
<div className={styles.description}>Selected User : {user.name}</div>
</main>
</>
);
};

// this function gets called during the build time
export async function getStaticPaths() {
// calling an external API to fetch all data
const res = await fetch("https://jsonplaceholder.typicode.com/users");
const users = await res.json();

const paths = users.map((item) => ({
params: { id: item.id.toString() },
}));

//these paths will get pre-rendered only at build time.
// { fallback: false } means other routes should 404.
return { paths, fallback: false };
}

// This also gets called at build time
export async function getStaticProps({ params }) {
// this fetch call has been made only to get the specific data
const res = await fetch(
`https://jsonplaceholder.typicode.com/users/${params.id}`
);
const user = await res.json();

return { props: { user } };
}

export default Post;

Below is the output of above code

Next.js has advised that you should use getStaticPaths if you are pre-rendering pages that use dynamic routes and if the data is coming from one of the sources from the below list

  • headless CMS
  • database
  • filesystem

You can learn more about getStaticPaths using this guide.

Server-side rendering

A page that uses server-side rendering as its pre-rendering form, generates HTML on each request.

If your page shows data that are getting updated frequently, then Server-side rendering is the advised form to be used for pre-rendering. But this would be much slower than the static generation.

If you need to configure a page in your app for server-side rendering, you have to include getServerSideProps function which will get called by the server on each request.

import styles from "../../styles/Home.module.css";

export default function Component({ users }) {
return (
<>
<main className={styles.main}>
<h1>Server-side rendering</h1>
<div className={styles.description}>
<ul>
{users.map((user) => (
<li key={user.email}>{user.name}</li>
))}
</ul>
</div>
</main>
</>
);
}

// this function gets called on each request
export async function getServerSideProps() {
// calling an external API to fetch data
const res = await fetch("https://jsonplaceholder.typicode.com/users");
const users = await res.json();

// this returning data can be accessed from the component using the prop name
return { props: { users } };
}

Follow this guide to learn more about getServerSideProps

References

Pre-rendering and Data Fetching (Next.js Learn Guide) — https://nextjs.org/learn/basics/data-fetching/pre-rendering

Next.js Docs on Pre-rendering — https://nextjs.org/docs/basic-features/pages

My Github Repo used for this article — https://github.com/sankharr/next_pre-render


Pre-rendering in Next.js was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Sankha Rathnayake

Background Image by Gradienta on Unsplash

What is pre-rendering?

Pre-rendering means generating HTML for each page in advance, together with minimal javascript code needed for that page.

After the page gets loaded into the browser, Javascript code gets executed and makes the page fully interactive. This part of the process is known as hydration.

Why pre-render?

  1. Pre-rendering improves performance
  • In a typical react app, you need to wait until the javascript code gets loaded into the browser and gets executed. Because of that, it will take some more time to render the UI
  • With a pre-rendered page, the HTML is already generated and loads faster

2. Pre-rendering helps with SEO

  • If you are building a blog or e-commerce site, SEO is a concern.
  • If you examine the source code of a web app created using CRA(create-react-app), you will only see a div tag with id equal to root in its body. That’s because its content is getting rendered using client-side rendering. If a search engine hits a such page, the search engine won’t be able to see the content. Because of that, a typical react app created using CRA, is not SEO friendly.
  • If the search engine hits a pre-rendered page that is created using Next.js, all the content is present in the source code which will help to index that page.

A test to check pre-rendering in an existing website

Let’s do a small test to check whether a given website is configured with pre-rendering.

  1. First, visit both of those pages and see if they are working.
  2. Now you have to disable javascript in your browser. Pick the relevant guide for the browser that you are using, to disable javascript
    Chrome/Brave Guide
    Firefox Guide
    Safari Guide
  3. After disabling javascript, you have to visit those two sites again using the same browser tab (which you disabled javascript) to check whether they are working.
    You’ll notice that Shu’s page is working fine and the CRA page is showing a message saying that ‘You need to enable JavaScript to run this app.’ You are seeing this message because the app is not pre-rendered into static HTML.
  • On Shu’s page, a pre-rendered HTML will be displayed during the initial load. After that, the javascript code gets loaded into the browser and then the app becomes interactive (This process is known as hydration).
  • On CRA page, there’s nothing during the initial load because the javascript is not getting loaded during the initial load. Once the browser loads the javascript code, the whole page gets rendered and becomes interactive.

Forms of Pre-rendering

There are two forms of pre-rendering in Next.js.

  1. Static Generation
  2. Server-side rendering

We can configure a page of a Next.js app to pre-render in either one of these forms. But ‘Static Generation’ is the form that is recommended by Next.js Team.

Static Generation

A page that uses Static Generation as its pre-rendering form, generates its HTML during the build time.
In production, This process takes place only when you run next build command. But in development mode (when you run npm run dev), pages will get pre-rendered on every request.

The HTML that gets generated using this process can be reused on each request and also it can be cached by a CDN.

Static Generation will automatically happen when there’s no data that component needs to be fetched from an external source (External API, querying the database etc.)

But if you have to fetch some data from an external source, you will have to use getStaticProps function to fetch those data.

Static generation is advised to be used if the data in your page are not getting changed frequently (For example, blog posts, marketing pages, e-commerce product listing, help and documentation, etc.)

Below is a code of a Next.js component where it fetches a list of users from a free API. Here we have used getStaticProps to fetch data.

// pages/sg/index.js

import styles from "../../styles/Home.module.css";
import Link from "next/link";

export default function Component({ users }) {
return (
<>
<main className={styles.main}>
<h1>Static Generation</h1>
<div className={styles.description}>
<ul>
{users.map((user) => (
<li key={user.email}><Link href={`/sg/${user.id}`}>{user.name}</Link></li>
))}
</ul>
</div>
</main>
</>
);
}

// this function gets called during the build time
export async function getStaticProps() {
// calling an external API to fetch data
const res = await fetch("https://jsonplaceholder.typicode.com/users");
const users = await res.json();

// this returning data can be accessed from the component using the prop name
return { props: { users } };
}

Below is the output of that code.

Output of Static Generation Code

This guide will give you more information about getStaticProps

If you want to route to a specific page (which contains more details about that specific user) when you click on a name in that list of users above, you can call getStaticPaths() function from a dynamic page.

// pages/sg/[id].js

import styles from "../../styles/Home.module.css";

const Post = ({ user }) => {
console.log("user", user);

return (
<>
<main className={styles.main}>
<h1>Static Generation (Paths)</h1>
<div className={styles.description}>Selected User : {user.name}</div>
</main>
</>
);
};

// this function gets called during the build time
export async function getStaticPaths() {
// calling an external API to fetch all data
const res = await fetch("https://jsonplaceholder.typicode.com/users");
const users = await res.json();

const paths = users.map((item) => ({
params: { id: item.id.toString() },
}));

//these paths will get pre-rendered only at build time.
// { fallback: false } means other routes should 404.
return { paths, fallback: false };
}

// This also gets called at build time
export async function getStaticProps({ params }) {
// this fetch call has been made only to get the specific data
const res = await fetch(
`https://jsonplaceholder.typicode.com/users/${params.id}`
);
const user = await res.json();

return { props: { user } };
}

export default Post;

Below is the output of above code

Next.js has advised that you should use getStaticPaths if you are pre-rendering pages that use dynamic routes and if the data is coming from one of the sources from the below list

  • headless CMS
  • database
  • filesystem

You can learn more about getStaticPaths using this guide.

Server-side rendering

A page that uses server-side rendering as its pre-rendering form, generates HTML on each request.

If your page shows data that are getting updated frequently, then Server-side rendering is the advised form to be used for pre-rendering. But this would be much slower than the static generation.

If you need to configure a page in your app for server-side rendering, you have to include getServerSideProps function which will get called by the server on each request.

import styles from "../../styles/Home.module.css";

export default function Component({ users }) {
return (
<>
<main className={styles.main}>
<h1>Server-side rendering</h1>
<div className={styles.description}>
<ul>
{users.map((user) => (
<li key={user.email}>{user.name}</li>
))}
</ul>
</div>
</main>
</>
);
}

// this function gets called on each request
export async function getServerSideProps() {
// calling an external API to fetch data
const res = await fetch("https://jsonplaceholder.typicode.com/users");
const users = await res.json();

// this returning data can be accessed from the component using the prop name
return { props: { users } };
}

Follow this guide to learn more about getServerSideProps

References

Pre-rendering and Data Fetching (Next.js Learn Guide) — https://nextjs.org/learn/basics/data-fetching/pre-rendering

Next.js Docs on Pre-rendering — https://nextjs.org/docs/basic-features/pages

My Github Repo used for this article — https://github.com/sankharr/next_pre-render


Pre-rendering in Next.js was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Sankha Rathnayake


Print Share Comment Cite Upload Translate Updates
APA

Sankha Rathnayake | Sciencx (2022-12-22T03:35:17+00:00) Pre-rendering in Next.js. Retrieved from https://www.scien.cx/2022/12/22/pre-rendering-in-next-js/

MLA
" » Pre-rendering in Next.js." Sankha Rathnayake | Sciencx - Thursday December 22, 2022, https://www.scien.cx/2022/12/22/pre-rendering-in-next-js/
HARVARD
Sankha Rathnayake | Sciencx Thursday December 22, 2022 » Pre-rendering in Next.js., viewed ,<https://www.scien.cx/2022/12/22/pre-rendering-in-next-js/>
VANCOUVER
Sankha Rathnayake | Sciencx - » Pre-rendering in Next.js. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/12/22/pre-rendering-in-next-js/
CHICAGO
" » Pre-rendering in Next.js." Sankha Rathnayake | Sciencx - Accessed . https://www.scien.cx/2022/12/22/pre-rendering-in-next-js/
IEEE
" » Pre-rendering in Next.js." Sankha Rathnayake | Sciencx [Online]. Available: https://www.scien.cx/2022/12/22/pre-rendering-in-next-js/. [Accessed: ]
rf:citation
» Pre-rendering in Next.js | Sankha Rathnayake | Sciencx | https://www.scien.cx/2022/12/22/pre-rendering-in-next-js/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.