Next.js provides three functions to fetch data for pre-rendered pages:
getStaticProps():
- Used for static generation (pre-rendering technique)
- Fetches data at build-time
- When an async function getStaticProps() is called from the page component, the next.js will pre-render this page at build time using the props returned by that function (see Examples)
- The context parameter used as an argument of getStaticProps() function is an object containing following parameters (see details here):
- params
- preview
- previewData
- locale
- locals
- defaultLocale
- getStaticProps() function returns an object with following parameters (see details here):
- props (required)
- revalidate
- notFound
- redirect
- Imports used inside the getStaticProps() function are not bundled for the client side
- Server side code can be written inside the getStaticProps() function e.g. to read files on the server or to communicate with the database
- API routes defined inside the next.js app should not be called inside getStaticProps() function using fetch() instead import the API route and call its function
- Incremental Static Regeneration
- Used to update the statically served page in the background after some interval defined as revalidate parameter
- Query parameters are not available inside the getStaticProps() function because it runs on the build-time instead of request-time
- Server-side code (e.g. database queries) can be written securely inside this function because this function only runs on the server side and is not included in client-side bundle
- This function saves the returned data inside a JSON file along with the HTML file which can then be used for future page requests using next/link or next/router
- This means that in client-side page transitions, the getStaticProps() function is not called instead the data saved in the JSON file is passed to the component
- getStaticProps() function can only be exported from pages
- In development (npm run dev), getStaticProps() function is called on every request
Example (JavaScript):
//https://nextjs.org/docs/basic-features/data-fetching
// posts will be populated at build time by getStaticProps()
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>{post.title}</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. See the "Technical details" section.
export async function getStaticProps(context) {
// Call an external API endpoint to get posts.
// You can use any data fetching library
const res = await fetch('https://.../posts')
const posts = await res.json()
// By returning { props: posts }, the Blog component
// will receive `posts` as a prop at build time
return {
props: {
posts,
},
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every second
revalidate: 1, // In seconds
}
}
export default Blog
Example (TypeScript):
import { InferGetStaticPropsType } from 'next'
type Post = {
author: string
content: string
}
export const getStaticProps = async (context) => {
const res = await fetch('https://.../posts')
const posts: Post[] = await res.json()
return {
props: {
posts,
},
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every second
revalidate: 1, // In seconds
}
}
function Blog({ posts }: InferGetStaticPropsType<typeof getStaticProps>) {
// will resolve posts to type Post[]
}
export default Blog
getStaticPaths():
- Used for pre-rendering of paths (or dynamic routes e.g. /pages/posts/[id].js) at build-time
- This function need to return paths object (required)
- The paths returned using paths object are pre-rendered at build-time
- Fallback key is also required and can have either true or false values
- fallback: false means that the pages other than the returned from paths object will show 404
- fallback: false is useful if there are small number of pages to be statically generated otherwise the build time will be increased
- fallback: true can be used if you want to pre-render some pages at build-time then load the other pages when they are requested using the Fallback pages (see example – fallback: true)
fallback: true
is useful if your app has a very large number of static pages that depend on data (think: a very large e-commerce site). You want to pre-render all product pages, but then your builds would take forever.Instead, you may statically generate a small subset of pages and use
fallback: true
for the rest. When someone requests a page that’s not generated yet, the user will see the page with a loading indicator. Shortly after,getStaticProps
finishes and the page will be rendered with the requested data. From now on, everyone who requests the same page will get the statically pre-rendered page.This ensures that users always have a fast experience while preserving fast builds and the benefits of Static Generation.
https://nextjs.org/docs/basic-features/data-fetching#when-is-fallback-true-useful
fallback: true
will not update generated pages, for that take a look at Incremental Static Regeneration.
Example (fallback: false):
// pages/posts/[id].js
function Post({ post }) {
// Render post...
}
// This function gets called at build time
export async function getStaticPaths() {
// Call an external API endpoint to get posts
const res = await fetch('https://.../posts')
const posts = await res.json()
// Get the paths we want to pre-render based on posts
const paths = posts.map((post) => ({
params: { id: post.id },
}))
// We'll pre-render only these paths 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 }) {
// params contains the post `id`.
// If the route is like /posts/1, then params.id is 1
const res = await fetch(`https://.../posts/${params.id}`)
const post = await res.json()
// Pass post data to the page via props
return { props: { post } }
}
export default Post
Example (fallback: true):
// pages/posts/[id].js
import { useRouter } from 'next/router'
function Post({ post }) {
const router = useRouter()
// If the page is not yet generated, this will be displayed
// initially until getStaticProps() finishes running
if (router.isFallback) {
return <div>Loading...</div>
}
// Render post...
}
// This function gets called at build time
export async function getStaticPaths() {
return {
// Only `/posts/1` and `/posts/2` are generated at build time
paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
// Enable statically generating additional pages
// For example: `/posts/3`
fallback: true,
}
}
// This also gets called at build time
export async function getStaticProps({ params }) {
// params contains the post `id`.
// If the route is like /posts/1, then params.id is 1
const res = await fetch(`https://.../posts/${params.id}`)
const post = await res.json()
// Pass post data to the page via props
return {
props: { post },
// Re-generate the post at most once per second
// if a request comes in
revalidate: 1,
}
}
export default Post