如何用Next.js SSG与Storyblok隐藏页面Slug中的虚拟文件夹
解决方案:去掉Storyblok虚拟文件夹的URL路径(Next.js SSG场景)
核心思路
绕过单个虚拟文件夹的限制,通过批量获取所有虚拟文件夹下的故事并处理slug,同时在静态渲染时反向推导Storyblok的完整路径,实现URL中隐藏虚拟文件夹的需求。
具体实现步骤
1. 在[[...slug]].js的getStaticPaths中生成干净的URL路径
调用Storyblok API拉取所有目标故事(覆盖所有语言、所有虚拟文件夹),对每个故事的full_slug做切割处理,剔除中间的虚拟文件夹部分:
export async function getStaticPaths() { // 定义所有需要处理的虚拟文件夹 const virtualFolders = ['website', 'landing-page']; const paths = []; // 替换为你的实际语言列表 const languages = ['en', 'zh']; for (const lang of languages) { // 拉取当前语言下所有虚拟文件夹中的故事 const stories = await storyblokApi.get(`cdn/stories`, { version: 'published', starts_with: `${lang}/`, is_startpage: false, }); for (const story of stories.data.stories) { const slugParts = story.full_slug.split('/'); // 定位并移除虚拟文件夹部分 const virtualFolderIndex = slugParts.findIndex(part => virtualFolders.includes(part)); if (virtualFolderIndex !== -1) { slugParts.splice(virtualFolderIndex, 1); } // 生成Next.js所需的path格式 paths.push({ params: { slug: slugParts } }); } } return { paths, fallback: 'blocking', // 根据业务需求选择true/blocking/false }; }
2. 在getStaticProps中反向推导Storyblok完整路径
用户访问干净URL(如/en/about)时,遍历所有虚拟文件夹,拼接出可能的Storyblok完整路径,找到匹配的故事:
export async function getStaticProps({ params }) { const virtualFolders = ['website', 'landing-page']; const slugParts = params.slug; let story = null; // 遍历虚拟文件夹,尝试拼接完整路径并请求API for (const folder of virtualFolders) { const fullSlugParts = [...slugParts]; // 在语言前缀后插入虚拟文件夹(适配你的路径规则) fullSlugParts.splice(1, 0, folder); const fullSlug = fullSlugParts.join('/'); try { const response = await storyblokApi.get(`cdn/stories/${fullSlug}`, { version: 'published', }); story = response.data.story; break; // 找到匹配项后停止遍历 } catch (err) { // 当前路径无匹配,继续尝试下一个虚拟文件夹 continue; } } if (!story) { return { notFound: true }; } return { props: { story, }, revalidate: 60, // 按需设置缓存刷新时间 }; }
额外注意事项
- 路径冲突处理:如果不同虚拟文件夹下存在相同内容slug(如
en/website/about和en/landing-page/about),需在业务层定义优先级(比如优先取website下的内容),避免匹配错误。 - 多语言适配:若语言前缀规则不同(如放在URL末尾),需调整slug切割和拼接的逻辑。
- 性能优化:可在
getStaticPaths中缓存拉取的故事列表,减少重复API请求;也可通过Storyblok的filter_query参数过滤掉不需要的故事。
替代方案:自定义URL字段
如果上述方法的API请求次数过多,可在Storyblok的故事模型中添加自定义字段(如desired_url),手动填写期望的URL路径(如en/about):
- 在
getStaticPaths中拉取所有故事,用desired_url字段生成paths。 - 在
getStaticProps中,通过params.slug拼接成desired_url,再调用API拉取对应故事(需确保desired_url与full_slug的映射关系准确)。
内容的提问来源于stack exchange,提问作者thiagohiguchi
相关产品推荐
相关产品推荐

