You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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):

  1. 在getStaticPaths中拉取所有故事,用desired_url字段生成paths。
  2. 在getStaticProps中,通过params.slug拼接成desired_url,再调用API拉取对应故事(需确保desired_url与full_slug的映射关系准确)。

内容的提问来源于stack exchange,提问作者thiagohiguchi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 00:55:25