NextJS带版本前缀的可选路由段实现方案咨询
在NextJS中实现多版本文档路由方案
针对你需要的多版本文档路由(/foo/bar对应最新版本,/x.y.z/foo/bar对应指定旧版本),同时共享渲染逻辑的需求,以下是两种适配不同NextJS路由体系的实现方案:
方案一:NextJS 13+ App Router
利用路由组、动态段正则约束和重写规则实现,既能避免误匹配,又能统一渲染逻辑。
1. 目录结构
创建带路由组的动态路由结构,路由组(docs)不会影响最终URL路径:
app/ └── (docs)/ └── [version]/ └── [...slug]/ └── page.tsx components/ └── DocsPage.tsx # 统一渲染组件
2. 配置路由重写与匹配规则
在next.config.js中添加重写规则,将不带版本的路径指向latest版本,同时限制[version]仅匹配版本号格式(如x.y.z):
/** @type {import('next').NextConfig} */ const nextConfig = { async rewrites() { return [ // 重写无版本路径到latest版本 { source: '/:slug*', destination: '/latest/:slug*', // 排除已带合法版本号的路径 missing: [ { type: 'pathname', value: '/:version(\\d+\\.\\d+\\.\\d+)/:slug*', }, ], }, ]; }, }; module.exports = nextConfig;
如果需要支持更宽松的版本格式(如x.y、x或预发布版x.y.z-beta),可将正则调整为^\\d+(\\.\\d+){0,2}(-[a-zA-Z0-9]+)?$
3. 统一渲染逻辑实现
在app/(docs)/[version]/[...slug]/page.tsx中处理版本参数,调用统一的渲染组件:
import DocsPage from '@/components/DocsPage'; import { getDocData } from '@/lib/docs'; type Props = { params: { version: string; slug: string[]; }; }; export default async function Page({ params }: Props) { const { version, slug } = params; // 将latest映射为实际的最新版本号(可从配置或接口获取) const actualVersion = version === 'latest' ? '2.0.0' : version; // 根据版本和slug获取对应文档数据 const docData = await getDocData(actualVersion, slug.join('/')); return <DocsPage data={docData} version={actualVersion} />; } // 静态生成场景:预生成所有版本+文档路径的组合 export async function generateStaticParams() { const versions = ['1.0.0', '2.0.0', 'latest']; // 实际可从文档源(如Markdown文件目录)自动获取所有slug const slugs = ['foo/bar', 'foo/baz', 'guide/quick-start']; return versions.flatMap(version => slugs.map(slug => ({ version, slug: slug.split('/'), })) ); }
4. 统一渲染组件
将文档渲染逻辑抽离到components/DocsPage.tsx,实现逻辑复用:
type DocsPageProps = { data: { title: string; content: string }; // 根据实际文档数据定义类型 version: string; }; export default function DocsPage({ data, version }: DocsPageProps) { return ( <div className="docs-container"> <div className="version-tag">当前版本:{version}</div> <h1>{data.title}</h1> <div className="doc-content">{data.content}</div> </div> ); }
方案二:NextJS Pages Router
通过自定义重写规则和动态路由页面实现,适配NextJS 12及更早版本。
1. 目录结构
创建动态路由页面,所有文档请求都通过该页面处理:
pages/ └── [version]/ └── [...slug].js components/ └── DocsPage.js # 统一渲染组件
2. 配置路由重写
在next.config.js中添加重写规则,逻辑同App Router:
module.exports = { async rewrites() { return [ { source: '/:slug*', destination: '/latest/:slug*', missing: [ { type: 'pathname', value: '/:version(\\d+\\.\\d+\\.\\d+)/:slug*', }, ], }, ]; }, };
3. 动态路由页面处理
在pages/[version]/[...slug].js中获取版本和slug,传递给统一组件:
import DocsPage from '../../components/DocsPage'; import { getDocData } from '../../lib/docs'; export async function getServerSideProps(context) { const { version, slug } = context.params; const actualVersion = version === 'latest' ? '2.0.0' : version; const docData = await getDocData(actualVersion, slug.join('/')); return { props: { data: docData, version: actualVersion, }, }; } // 静态生成场景替换为getStaticPaths和getStaticProps // export async function getStaticPaths() { /* 生成所有路径 */ } // export async function getStaticProps(context) { /* 获取数据 */ } export default DocsPage;
4. 统一渲染组件
同App Router方案,将渲染逻辑抽离到components/DocsPage.js即可。
关键注意事项
- 版本号匹配规则:根据实际版本格式调整正则,避免误匹配非版本路径。
- 静态生成优化:如果采用SSG,需确保所有版本和文档路径的组合都被预生成,可通过脚本自动扫描文档目录生成
generateStaticParams或getStaticPaths的返回值。 - 版本切换:可在页面顶部添加版本选择器,通过链接到
/${version}/foo/bar实现版本切换。
内容的提问来源于stack exchange,提问作者Sean Mackesey
相关产品推荐
相关产品推荐

