【问题标题】:NextJS case insensitive route for SSG pagesSSG 页面的 NextJS 不区分大小写的路由
【发布时间】:2021-09-07 23:41:03
【问题描述】:

我正在使用 NextJS 将 CSV 数据转换为静态页面。每个页面都是pages/[slug].jsx。我在 [slug].jsx getStaticPaths()getStaticProps() 函数内的 slug 值上调用 toLowerCase()。生成的页面是小写的。例如/ab101、/ab102、/cc500 都解析到 pages/[slug].jsx 页面。

不幸的是,人们可能手动输入 url,并且可能使用大写或混合大小写作为 slug 值,目前导致 404。

问题:如何使路由对 slug 值不区分大小写?

更新

当我从getStaticPaths() 返回fallback: true 时,即使没有完全匹配的路径,我的[slug].jsx 文件也会被命中。然后我可以检查isFallback,如下面的 Anish Antony 所示。

此外,当找不到页面时,传递给我的页面的 items 参数将是未定义的。路由器的pathname 值是"/[slug]" 而不是“slug”的值。但是,有一个 asPath 值包含有用的数据,例如/mixedCaseSlug?param=value&foo=bar.

当页面呈现时,我检查它是否是一个后备。如果是,则显示 LOADING... 消息。接下来将显示它并调用 getStaticProps() 来生成“缺失”页面。然后,您将使用页面数据重新渲染。如果 getStaticProps 无法获取页面数据,我会推送一条路径,该路径将通向内置的 404 页面。

export default function Page({ item }) {
  const { isFallback, push } = useRouter()
  const hasPageData = item && Object.keys(item).length > 0
  useEffect(() => {
    if (!isFallback && !hasPageData) {
      push('/page-not-found/error')
    }
  }, [isFallback, hasPageData])
  const loadingMsg = <div>Loading...</div>
  const notFoundMsg = <div>Page not found</div>
  return isFallback ? loadingMsg : hasPageData ? <Item item={item} /> : notFoundMsg
}

我需要将getStaticProps() 更新为小写slug 参数,因为它现在可能是大小写混合,但我们想找到我们的页面数据。而且我需要考虑到确实没有 slug 数据的情况。

export async function getStaticProps({ params }) {
  const { slug } = params
  const item = data.find(o => o.Practice_Code.trim().toLowerCase() === slug.toLowerCase())
  return {
    props: {
      item: item ? item : {}
    }
  }
}

这一切看起来都很笨拙,所以我仍然想知道是否有更好的方法。

【问题讨论】:

    标签: next.js url-routing


    【解决方案1】:

    NextJS 路由区分大小写。您可以使用 getStaticPaths 中的回退属性来捕获与 getStaticPaths 中默认提供的路由大小写不同的路由。

    编辑:我已经根据与 Dave 的讨论更新了答案。

    我们可以给 fallback:true 或 fallback:"blocking" ,如果我们给 fallback:true 我们可以显示一个自定义组件,该组件将一直显示到页面加载的时间。对于 fallback:"blocking" 不返回新路径通过 getStaticPaths 将等待生成 HTML,

    当我们给出 fallback:true 或“阻塞”静态页面时,用户第一次访问该站点时将生成该页面,并且生成的页面将被提供以供进一步访问。

    示例代码

    export async function getStaticPaths() {
      const idList = await fetchAllIds();
      const paths = [
      ];
      idList.forEach((id) => {paths.push(`/posts/${id}`)})
      return { paths, fallback: true };
    }
    

    我们需要注意的是我们在 getStaticProps 中的代码应该不区分大小写以获取数据,而不管 url 中提供的数据。

    
    export async function getStaticProps({ params }) {
      const { slug } = params;
    
     try {
        /// This fetch api should be able to fetch the data irrespective of the case of the slug 
    or we should convert it to the required case before passing it as a parameter to API
        const data= await fetchSlugDetails(slug);
    //Same logic should be performed if you are getting data filtered based on slug from an existing array.
        return data? { props: { data} } : { notFound: true };
      } catch (error) {
        console.error(error);
        return { notFound: true };
      }
    
    }
    
    
    

    注意:如果你使用 fallback:true,你必须处理 notfound 情况和 fallback 情况。对于回退,您可以在静态生成页面时从 next/router 获取值 isFallback

    【讨论】:

    • 谢谢。那个 useEffect() 去哪里了?我的 pages/[slug].jsx 页面似乎没有被击中。是否有更多解决方案,例如在某处添加路由或 getStaticPaths() 后备参数?
    • 是的,我使用 fallback:true 和 getStaticPaths 并在我的组件中使用 isFallback,我已经使用我的应用程序中的示例代码编辑了答案。 (代码在 Vercel 部署后工作正常)
    • 我接受了您的回答,因为它为我指明了正确的方向。但是,它不能按原样工作。至少对于当前版本的 NextJS 来说不是。感谢您提供有关返回后备的提示:true。
    • 好的,我使用的是 10.0.3。如果可以的话,请在当前版本中发布工作代码。
    • 我在问题底部添加了它作为更新。
    猜你喜欢
    • 2014-03-10
    • 2021-10-12
    • 2020-01-26
    • 1970-01-01
    • 1970-01-01
    • 2014-03-27
    • 2015-06-06
    • 2016-11-24
    • 2016-12-16
    相关资源
    最近更新 更多