Several pitfalls in NextJS development
Table of Contents
Incremental Static Generation and Fallback
I am using incremental static generation and fallback in a blog site, to render posts from a Headless CMS elsewhere. The code looks something like this:
getStaticPaths
function
export const getStaticPaths: GetStaticPaths = async () => {
const postSlugs = await getNewestPostSlugs(); // maybe 20 - 30 slugs at build time.
const paths = postSlugs.map((slug) => ({
params: {
slug,
},
}));
return {
paths,
fallback: true,
};
};
getStaticProps
function:
export const getStaticProps: GetStaticProps<BlogViewPageProps> = async (
context
) => {
const postSlug = context.params?.postSlug;
if (!postSlug) {
return {
notFound: true,
};
}
const post = await getPostDataFromCMSBySlug(postSlug as string);
if (_.isNil(post)) {
return {
notFound: true,
};
}
return {
props: {
post,
},
revalidate: COMMON_CACHE_TIME,
};
};
Looks good right. So if I go to posts/post-1
and the post with slug post-1
doesn’t exist in the CMS, getStaticProps
should return a 404 not found
. The revalidate
option specifies a cache time for the statically generated page, so I thought if I go and create post-1
in the CMS, after COMMON_CACHE_TIME
, the old 404
page should be invalidated and NextJS should try and regenerate posts/post-1
again.
However, in the example above revalidate
option only apply to successfully generated page. If your post hit 404, it will stay 404 until the end of time, because there isn’t an revalidate
option for notFound
outcome of generating a page.
The correct code should be
export const getStaticProps: GetStaticProps<BlogViewPageProps> = async (
context
) => {
const postSlug = context.params?.postSlug;
if (!postSlug) {
return {
notFound: true,
revalidate: COMMON_CACHE_TIME, // add this
};
}
const post = await getPostDataFromCMSBySlug(postSlug as string);
if (_.isNil(post)) {
return {
notFound: true,
revalidate: COMMON_CACHE_TIME, // add this
};
}
return {
props: {
post,
},
revalidate: COMMON_CACHE_TIME,
};
};