I think this is quite a vanilla question but I can't find anything on Google.
I'm learning NextJs (using TypeScript) and I've got a site successfully working with dynamic routes, SSR, and incremental regeneration all setup and deployed to Vercel. Here's an example of the GetStaticProps
and GetStaticPaths
code in my dynamic route handler:
export const getStaticPaths: GetStaticPaths = async () => {
const routes = new CmsHelper().GetRoutes();
const paths = (await routes).items.map((item, index, items) => {
return item.fields.urlPath;
})
return {
paths: paths,
fallback: 'blocking',
};
}
export const getStaticProps: GetStaticProps = async (context) => {
const urlParts = context.params?.url as string[] || [];
const urlPath = `/${urlParts.join('/')}`;
const article = await new CmsHelper().GetArticle(urlPath);
return {
props: {
article
},
revalidate: 10,
}
}
If I request a new path that was published in the cms after build time, it successfully regenerates on the server and returns the page.
So far so good.
However, if I unpublish a route in my CMS... it is still returned by the app, unless I rebuild and redeploy (or otherwise cause the process to restart, in dev).
So my question is: how do I dynamically cause NextJs to remove a dynamic route from its GetStaticPaths cache?
I understand that GetStaticProps
is going to be called at most once every 10 seconds because of the revalidate
configuration. But as far as I know, GetStaticPaths
will only be called if a request comes in from a route that is not currently cached(?)
In other words, for an integration with a headless CMS, how can I support unpublishing or renaming pages with NextJs without triggering a rebuild/deploy?
Thanks in advance!
Maybe try this approach described here.
Also providing the code here for reference purposes.
// pages/blog/[slug].js
import {useRouter} from 'next/router'
import DefaultErrorPage from 'next/error'
export async function getStaticProps({ params }) {
// fetch data from CMS through params
const post = await getBlogItem(params.slug)
return {
props: {
post
}
}
}
export async function getStaticPaths() {
return {
fallback: true,
paths: []
}
}
export default function MyPage({post}) {
const router = useRouter()
if(router.isFallback) {
return <h1>Loading...</h1>
}
// This includes setting the noindex header because static files always return a status 200 but the rendered not found page page should obviously not be indexed
if(!post) {
return <>
<Head>
<meta name="robots" content="noindex">
</Head>
<DefaultErrorPage statusCode={404} />
</>
}
return <h1>{post.title}</h1>
}
So, instead of deleting/clearing the cache, maybe try to handle successfully that the content you are fetching is "unpublished" and if so, you can display a 404 Not found
page or something of your choice.
Something like this:
export async function getStaticProps(context) {
const {params: {id}} = context
let data;
try {
data = await httpClient...
} catch (err) {
if (not err is caused due to content being unpublished){
// re throw it
throw err;
}
// Else handle it gracefully
data = null;
}
return {
props: {
data,
},
revalidate: 1
};
}
and then on your View:
export default function Data(props) {
const {data} = props;
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>
}
if (!data) {
return (
<>
<Head>
<meta name="robots" content="noindex"/>
</Head>
<DefaultErrorPage statusCode={404}/>
</>
)
}
return <DataView {...data} />;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With