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

Next.js 13 App Router:URL用slug但需获取ID的静态路由问题

解决方案

1. 在generateStaticParams中返回完整页面元数据

不要只返回slug,从CMS拉取所有页面的slug、ID、locale信息,将这些字段全部作为静态参数返回。这样Page组件能直接拿到ID和locale,无需通过slug二次查询或调用headers()获取locale,完全支持静态生成。

示例代码:

// app/[[...slug]]/page.tsx
import { getCmsPages } from '@/lib/cms'

export async function generateStaticParams() {
  // 从CMS获取全量页面元数据:包含slug、id、locale
  const cmsPages = await getCmsPages()

  return cmsPages.map(page => ({
    // 将slug拆分为数组适配[[...slug]]路由,如"tech/react-guide" => ["tech", "react-guide"]
    slug: page.slug.split('/'),
    // 传递ID和locale给Page组件
    id: page.id,
    locale: page.locale,
  }))
}

2. Page组件直接使用静态传递的参数

Page组件的params会包含generateStaticParams返回的所有字段,直接用ID请求文章数据即可,全程静态生成,不会触发SSR。

示例代码:

export default async function Page({ params }: { params: { slug: string[], id: string, locale: string } }) {
  // 用静态传递的ID和locale请求文章详情
  const article = await getArticleById(params.id, params.locale)

  return (
    <div>
      <h1>{article.title}</h1>
      <div dangerouslySetInnerHTML={{ __html: article.content }} />
    </div>
  )
}

3. 多语言路由的优化处理(可选)

如果你的站点用路由前缀(如/en/blog/post、/zh/blog/post)区分语言,可在next.config.js配置官方i18n路由:

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  i18n: {
    locales: ['en', 'zh'],
    defaultLocale: 'en',
  },
}

module.exports = nextConfig

配置后,generateStaticParams返回的locale会自动对应路由前缀,Page组件的params也会直接包含locale字段,无需手动从slug拆分。

问题根源说明

  • 之前仅返回slug,params自然只有slug字段,ID为undefined;
  • 调用headers()获取locale属于请求时动态数据,会触发SSR,必须在构建阶段就把locale与页面数据绑定,才能实现静态生成。

额外注意事项

  • 确保CMS能一次性返回全量页面元数据,数据量大时可分页拉取,保证构建阶段获取完整数据;
  • 若不同locale下存在重复slug,依赖ID查询数据可避免冲突;
  • 需支持内容自动更新时,可添加增量静态再生(ISR)配置:
// 在page.tsx中添加,每60秒重新生成页面
export const revalidate = 60

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 18:45:07