首页 > 解决方案 > 如何清除 NextJs GetStaticPaths 缓存/“取消发布”动态路由?

问题描述

我认为这是一个很普通的问题,但我在谷歌上找不到任何东西。

我正在学习 NextJs(使用 TypeScript),并且我有一个站点成功地使用动态路由、SSR 和增量再生,所有设置和部署到 Vercel。这是我的动态路由处理程序中的GetStaticPropsand代码示例:GetStaticPaths

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,
    }
}

如果我在构建时间后请求在 cms 中发布的路径,它会成功在服务器上重新生成并返回页面。

到目前为止,一切都很好。

但是,如果我在我的 CMS 中取消发布路由......它仍然由应用程序返回,除非我重建和重新部署(或以其他方式导致进程在开发中重新启动)。

所以我的问题是:如何动态地使 NextJs 从其 GetStaticPaths 缓存中删除动态路由?

我知道GetStaticProps由于配置原因,最多每 10 秒调用一次revalidate。但据我所知,GetStaticPaths只有当请求来自当前未缓存的路由时才会调用(?)

换句话说,对于与无头 CMS 的集成,如何在不触发重建/部署的情况下支持使用 NextJs 取消发布或重命名页面?

提前致谢!

标签: typescriptnext.jscontentful

解决方案


也许试试这里描述的这种方法

还在这里提供代码以供参考。

// 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>
}

因此,与其删除/清除缓存,不如尝试成功处理您正在获取的内容是“未发布”的,如果是这样,您可以显示一个404 Not found页面或您选择的内容。

像这样的东西:

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
    };
}

然后在您的视图上:

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} />;

}

推荐阅读