如何在Next.js中保留Contentful Slug中的斜杠
Next.js处理Contentful带斜杠Slug的URL编码问题
问题场景
在Contentful + Next.js项目中,从Contentful获取的文章slug包含斜杠(例如news-insights/blogname),但通过getStaticPaths生成路径时,斜杠会被自动编码为%2F,导致页面URL变成news-insights%2Fblogname,无法形成预期的层级化URL结构。
原代码如下:
// src/pages/[slug].jsx export const getStaticPaths = async () => { const response = await client.getEntries({ content_type: "blog", locale: "nl", }); const paths = response.items.map((item) => { return { params: { slug: item.fields.slug }, }; }); return { paths, fallback: true, }; };
曾尝试直接传入数组形式的slug(params: { slug: ['news-insights', 'blogname'] }),但未生效,期望生成并访问news-insights/blogname格式的URL。
解决方案
要保留slug中的斜杠并生成层级化URL,需要利用Next.js的动态路由捕获所有分段特性,具体步骤如下:
1. 修改页面文件命名
将原有的src/pages/[slug].jsx重命名为src/pages/[...slug].jsx。这种命名方式会让Next.js将URL中的所有分段捕获为一个数组。
2. 调整getStaticPaths的路径生成逻辑
将带斜杠的slug分割为字符串数组,作为params.slug的值:
export const getStaticPaths = async () => { const response = await client.getEntries({ content_type: "blog", locale: "nl", }); const paths = response.items.map((item) => { // 将带斜杠的slug分割为数组 const slugSegments = item.fields.slug.split('/'); return { params: { slug: slugSegments }, }; }); return { paths, fallback: true, }; };
3. 修改getStaticProps的参数处理
此时params.slug是一个数组,需要将其拼接回带斜杠的字符串,用于查询Contentful中对应的条目:
export const getStaticProps = async ({ params }) => { // 将数组形式的slug拼接回原始字符串 const slug = params.slug.join('/'); const response = await client.getEntries({ content_type: "blog", locale: "nl", 'fields.slug': slug, // 使用拼接后的slug查询 }); if (!response.items.length) { return { notFound: true }; } const blogPost = response.items[0]; return { props: { blogPost, }, revalidate: 60, // 可选:设置增量静态再生时间 }; };
原理说明
[...slug].jsx是Next.js的catch-all路由,会匹配/a/b/c这类多级路径,将['a','b','c']作为params.slug的值。- 通过
split('/')将Contentful返回的带斜杠slug拆分为数组,符合catch-all路由的参数格式,Next.js会自动将数组转化为层级化的URL路径,不会编码斜杠。 - 在
getStaticProps中再将数组拼接回原始slug字符串,确保能正确查询到Contentful中的对应内容。
内容的提问来源于stack exchange,提问作者JimOv
相关产品推荐
相关产品推荐

