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
相关产品推荐
相关产品推荐

