Next.js能否在构建时为静态页面自动生成链接?
Next.js 静态页面自动生成导航链接实现
完全可以实现自动生成页面跳转列表的效果,无需手动硬编码每一条链接,新增或删除静态页面时导航列表会在构建时自动同步更新,和Gatsby通过构建时节点生成页面列表的逻辑等效。
核心实现逻辑
利用Next.js getStaticProps 仅在构建阶段执行、可直接访问Node.js文件系统能力的特性,在构建时扫描pages目录结构,严格按照Pages Router的路由规则映射生成全量路由列表,传入对应页面渲染即可。
具体实现步骤
1. 编写构建时路由扫描工具
新建lib/pageRoutes.ts,实现目录递归扫描、路由映射逻辑,自动排除Next.js内置的特殊页面文件:
// lib/pageRoutes.ts import fs from 'fs' import path from 'path' // 排除Next.js内置特殊页面,避免被扫描到导航列表 const EXCLUDE_FILES = new Set(['_app.tsx', '_document.tsx', '404.tsx', 'index.tsx']) export type PageRoute = { path: string title: string } export function getStaticPageRoutes(): PageRoute[] { const pagesDir = path.join(process.cwd(), 'pages') const routes: PageRoute[] = [] // 递归扫描pages目录 function scanDir(currentPath: string, baseRoutePath = '') { const entries = fs.readdirSync(currentPath, { withFileTypes: true }) for (const entry of entries) { const fullPath = path.join(currentPath, entry.name) if (entry.isDirectory()) { // 扫描子目录下的index.tsx,映射为对应目录路由 const subRoute = `${baseRoutePath}/${entry.name}/` const indexFilePath = path.join(fullPath, 'index.tsx') if (fs.existsSync(indexFilePath)) { routes.push({ path: subRoute, title: formatPathToTitle(entry.name) }) } // 递归扫描嵌套子目录 scanDir(fullPath, subRoute) } else if (entry.isFile() && entry.name.endsWith('.tsx')) { // 处理根目录下的独立页面文件 if (EXCLUDE_FILES.has(entry.name)) continue // 跳过动态路由文件(文件名包含[]的为动态路由) if (entry.name.includes('[')) continue const fileName = entry.name.replace('.tsx', '') routes.push({ path: `/${fileName}/`, title: formatPathToTitle(fileName) }) } } } // 将驼峰格式的路径名转换为可读的展示标题 function formatPathToTitle(name: string) { return name .replace(/([A-Z])/g, ' $1') .replace(/^./, str => str.toUpperCase()) .trim() } scanDir(pagesDir) return routes }
2. 首页渲染自动生成的链接列表
修改首页代码,在getStaticProps中调用扫描工具获取全量路由列表,直接渲染跳转组件即可,无需手动编写每一条链接:
// pages/index.tsx import Link from 'next/link' import { getStaticPageRoutes } from '../lib/pageRoutes' // 构建时执行,拉取全量页面路由数据 export async function getStaticProps() { const routes = getStaticPageRoutes() return { props: { routes } } } export default function HomePage({ routes }) { return ( <ol> {routes.map(route => ( <li key={route.path}> <Link href={route.path}>{route.title}</Link> </li> ))} </ol> ) }
扩展能力
可完全覆盖Gatsby方案的自定义能力:
- 路由过滤:和Gatsby中根据frontmatter字段筛选页面的逻辑一致,可自定义规则过滤不需要展示在导航中的页面
- 自定义元数据:如果自动从文件名生成的标题不符合需求,可在每个页面文件中导出统一的
pageMeta字段,扫描时读取对应文件的元数据,实现自定义标题、排序权重、导航描述的效果 - 零成本维护:只要在
pages目录下新增或删除静态页面文件,下次构建时导航列表会自动同步变更,不需要手动修改首页的导航代码
注意事项
- 路由扫描逻辑仅在构建阶段的Node.js环境执行,文件系统相关的代码不会打包到客户端运行时代码中,无安全风险
- 生成的路由路径严格对齐Next.js Pages Router的解析规则,和实际可访问的页面路径完全一致,不会出现路由匹配错误
- 扫描逻辑已自动跳过带
[]的动态路由文件,避免生成无效跳转链接
内容的提问来源于stack exchange,提问作者msalla
相关产品推荐
相关产品推荐

