A new concept we need to be familiar with is pre-rendering.
By default, Next.js pre-renders every page. This means that Next.js generates HTML for each page in advance, instead of having it all done by client-side JavaScript. Pre-rendering can result in better performance and SEO.
Pre-rendering
Next.js allows choosing between two forms of pre-rendering: Static Generation and Server-side Rendering. The difference is in when it generates the HTML for a page.
Static Generation (Recommended)
The HTML is generated at build time (when you run next build
) and will be reused on each request. Statically generated pages can be cached by CDN to boost performance.
- If the content depends on external data, you need to use
getStaticProps
. - If the paths depend on external data you need
getStaticPaths
, usually in addition togetStaticProps
.
Server-side Rendering (SSR)
The HTML is generated on each request. This might be a better choince when a page shows frequently updated data, and the page content changes on every request.
- You need to use
getServerSideProps
.
Each generated HTML is associated with minimal JavaScript code necessary for that page. When a page is loaded by the browser, its JavaScript code runs and makes the page fully interactive. (This process is called hydration.)
Hydration is used in Angular and React as well.
However, Next.js allows you to choose which pre-rendering form to use for each page.
Following the documentation, I will work on the example by using static generation.
If you application doesn't require external data, all pages will automatically be statically generated when the app is built for production.
This is not often the case in real life.
Next.js allows to fetch data at build time by using exporting an async function called getStaticProps
.
Inside the getStaticProps
function we can make asynchronous operations like fetching data from a server.
The documentation proposes an example using markdown files but since json data is more common, I will show how to retrieve data from a local json file before fetching it from a server.
Using Static Generation To Read A Local Json File
While we could store a json file in the public folder, that is not very safe. So we create a new folder at the root level and we call it json.
Set Up Json Data
Create a folder at the root level and call it json.
Inside the json folder, create a file called data.json in which we can copy-paste a list of users from jsonplaceholder.
Read Json Data
Create another folder at the root level of the application and call it lib. Inside the lib folder create a file and name it localdata.js.
In localdata.js we are going to create a utily function to read data from the json file.
Inside localdata.js we can add the following code:
import fsPromises from 'fs/promises';
import path from 'path'
export async function getLocalData() {
// Get the path of the json file
const filePath = path.join(process.cwd(), 'json/data.json');
// Read the json file
const jsonData = await fsPromises.readFile(filePath);
// Parse data as json
const objectData = JSON.parse(jsonData);
return objectData
}
Display Data In Home
Now, we can display data in the Home component (index.js) by using the async getStaticProps
function.
Here there are a few things to notice, first we need to import the utility function getLocalData
in index.js.
//index.js
import Head from 'next/head';
import Layout, { siteTitle } from '../components/layout';
import utilStyles from '../styles/utils.module.css';
import Link from 'next/link';
import { getLocalData } from '../lib/localdata';
Second, we need to use the async function called getStaticProps
.
Inside the getStaticProps
function we can make asynchronous operations like fetching data from a server.
// index.js
...
import { getLocalData } from '../lib/localdata';
export async function getStaticProps() {
const localData = await getLocalData()
return {
props: { localData }
}
}
Finally, we can pass localData as a prop to the Home component as follows:
// index.js
...
export async function getStaticProps() {}
export default function Home({ localData }) {
...
return (
<>
...
<Layout home>
...
<section className={`${utilStyles.headingMd} ${utilStyles.padding1px}`}>
<h2 className={utilStyles.headingLg}>Blog</h2>
<ul className={utilStyles.list}>
{localData.map(({ id, name, website }) => (
<li className={utilStyles.listItem} key={id}>
<b>{id} - {name}</b>
<br />
{website}
</li>
))}
</ul>
</section>
</Layout>
</>
)
}
Here is how my page looks like at the moment:
You can find another example in this post on Medium
Otherwise, in the next post, we will read data from an API.
Top comments (2)
Interesting waiting for next post and thanks for sharing well explained👍👍👍
Thanks Okoro!
I really appreciate your comment:)