Table of Contents
What is pre-rendering?
Next.js official documents say that Next.js, by default, pre-renders every page in the application. What does that really mean? It means that the web page that you see on the browser receives to the browser as an HTML page with minimal javascript required to add interactivity to each HTML page. A user who sends a request to the server does not need to wait until javascript is loaded in the browser. Thus, pre-rendering is better in terms of performance and SEO and improves user experience compared to client-side rendering in which the user must wait until the initial JavaScipt loads in the browser to render an initial HTML page(React, by default use client-side rendering).
There are two forms of pre-rendering
- Static Generation
- Sever-side rendering ( SSR )
I am going to talk about Static Generation with you in this post
Pre-rendering with Static Site Generation(SSG)
- It happens at build time when you run the next build command( with npm run build/yarn build in the terminal). The HTML files generated will be reused on each web request later.
- SSG Can be done with or without external data.
- getStaticProps is essential in writing the server-side code to fetch external data
- At build time, Next.js generates a JSON file with external data along with the HTML files
- HTML and JSON are built once, and can then be served by CDN. This improves performance.
- SSG is ideal for pages that do not change their content from time to time.
- Marketing pages
- Blog posts
- E-commerce product listings
- Help and documentation
What is getStaticProps?
Next.js is a full-stack framework that you can develop complete production-ready web applications. This means you can write both client-side and server-side code. getStaticprops is a special function Next.js provides to execute server-side code. Whatever code you write inside this function never runs on the client-side.
So, what is the connection between Static Generation and getStaticProps?
Some static pages may not require any data, just HTML. But, others would need data to be fetched by a database, external API, or the file system. In such a case, we need to use getStaticProps.
How to use getStaticProps to fetch API data
Let’s see how we can build a static page with getStaticProps
I assume you know how to install Next.js and the very basics of Next.js. If not, please check Next.js setting up and routing in this article.
We are going to make a web app that displays a list of presidents in the USA
- Create a Next.js app running
npx create-next-app demo-next-app
- Create a file name president.js in that pages folder
- Add the following code
function PresidentList( { presidents }){
return(
<>
<h1>List of US presidents</h1>
{
presidents.map(
president =><div key={ president.id }>
<li>{ president.name }
</li>
</div>
)
}
</>
)
}
export default PresidentList
export async function getStaticProps(){
const response = await fetch('https://api.sampleapis.com/presidents/presidents',{
method:'GET',
headers:{
'Content-Type':'application/json'
}
});
const data = await response.json();
// console.log( data ) //UNCOMMENT TO SEE THE DATA RECEIVE FROM API
return {
props:{
presidents: data.slice(0,10),//take only 10 names from the list
},
}
}
There are two functions here
- PresidentList
This is the code that executes in the browser. It receives props in build time. These props are returned by the getStaticProps at the build time.
- getStaticProps
This code runs on the server. In the development mode, getStaticProps will run on every request you sent to the server. You can observe this if you uncomment the console.log() statement inside this function. The getStaticProps function fetches API data and returns an object. You must return an object in getStaticProps. The object contains the property props which itself is another object. This inner object contains a key-value pair containing the data. The console statement displays the fetched data on the console in the terminal and not in the console of the browser. This is because getStaticProps runs on the server-side.
However, in production, this function will run once when you execute “next build” with npm run build/ yarn build
- Replace the code in pages/index.js with the code below
import Link from 'next/link'
export default function Home() {
return (
<div className={styles.container}>
<Link href='/president'>
<a>Show me a list of US presidents</a>
</Link>
</div>
)
}
As you can notice that I have used the link component in this file. The link component there makes the transition between pages smooth, and I will explain how it happens later in this post.
Building the Next.js App
Now that you have developed this simple application in the development mode, it is time to build it.
- First, delete the .next folder created in the development mode. Optionally, you may delete any other sample files created in the default app.(ex: page/api/hello.js). But DO NOT delete _app.js.
- Then, In the terminal run “Npm run build” or “yarn build”
- This will run the next build command on package.json to create an optimized production build.
- The building process creates a .next folder. The content of this .next is different from that of the .next created in the development mode. After the successful completion, it should display the summary of the pages created.
As you can see the president.js uses both HTML and JSON. Here SSG stands for Static Site Generation. Next.js stores the API data received in getStaticProps in a JSON file.
- Now you can run the build version of the app with npm start/yarn start. You can run the application, by default, on localhost:3000.
Inspecting the files generated
Let us see what kind of files are actually running in the background when we start the application on localhsot:3000.
- Start your app on localost:3000
- Go to developer tools
- Right-click on the reload button and click on “Empty Cache and Hard Reload”. After that click on the “Network” tab.
- You will observe the following files.
As you can see the one that says “localhost” is the index.js file, which is an HTML file. Click on it and the preview tab. You will see the content. There are many js bundles and files here. Another important file here is the president.json file. Click on it. You can notice the pageProps used in this application.
- Now, in the application in the browser, click on the, “show me a list of presidents” link and note what happens in the network tab. You will not the president.json file is fetched.
- When you click on this link, you are using the next/link component(or next/router), the JSON file created in the build time is used. This means you will not send a new request to the server(i.e not call getStaticProps ). Thus, there is a smooth transition between pages. If you use a traditional anchor tag this will not be the case.
- Go back to the localhost:3000, right-click on reload and click “Empty Cache and Hard Reload” once again
- Now, instead of clicking on the “show me a list of presidents” link, enter http://localhost:3000/president ( i.e not using the next/link component) on the browser, and check what happens in the network tab.
You will notice and “president” file is generated. This is an HTML file. The between the pages is not as smooth as before when you click on the link on the browser that uses the next/link component, because the browser has to load the whole HTML page.
- This JSON file will be used in client-side routing through next/link or next/router. When you navigate to a page that’s pre-rendered using getStaticProps, Next.js fetches this JSON file (pre-computed at build time) and uses it as the props for the page component. This means that client-side page transitions will not call getStaticProps as only the exported JSON is used.
You can also do further experiments with this app by disabling javascript on the browser. You will still be able to render the pages without running javascript. This is not the case with React on the other hand.
Summary
Pre-rendering is an important aspect of Next.js that you must understand. It has two ways to pre-render. one of them is Static Site Generation(SSG). You can create web pages using SSG with or without external data. When you use external data, you need to use getStaticProps, a special function in Next.js inside which you can run the server-side code.