Next.js中创建动态index.js实现[country]/[state]/[city]全静态生成
实现多级路由全静态生成的操作步骤
1. 先定义全局静态地区数据源
因为所有内容部署前完全确定,先把层级结构定义为可全局调用的常量,比如存到/data/regions.js里:
// /data/regions.js export const regions = { "加拿大": { "魁北克省": ["蒙特利尔市"], "安大略省": ["多伦多市"] }, "美国": { "北卡罗来纳州": ["夏洛特市"], "佛罗里达州": ["奥兰多市"] } }
你之前省/州页面需要请求时生成的核心原因是:没有给省/州对应的动态路由预声明所有可能的路径参数,Next.js只能在用户请求时临时生成页面。
2. 调整pages目录结构,匹配路由规则
你的pages目录要按如下结构组织:
pages/ ├── index.js // 根页面:展示国家列表 └── [country] ├── index.js // 国家页:展示对应国家的省/州列表 └── [state] ├── index.js // 省/州页:展示对应州的城市列表 └── [city].js // 你已经完成的城市详情页
3. 逐个实现各层级页面的静态生成逻辑
所有动态路由的fallback都设置为false,确保未在构建时预生成的路径直接返回404,不会触发请求时生成逻辑。
3.1 根页面 pages/index.js
属于固定路由,不需要getStaticPaths,直接用getStaticProps拉取国家列表即可:
// pages/index.js import Link from 'next/link' import { regions } from '../data/regions' export default function Home({ countries }) { return ( <div> <h1>国家列表</h1> <ul> {countries.map(country => ( <li key={country}> <Link href={`/${encodeURIComponent(country)}`}>{country}</Link> </li> ))} </ul> </div> ) } export function getStaticProps() { return { props: { countries: Object.keys(regions) } } }
3.2 国家层级动态页 pages/[country]/index.js
用getStaticPaths预声明所有国家的路径参数:
// pages/[country]/index.js import Link from 'next/link' import { regions } from '../../data/regions' export default function CountryPage({ country, states }) { return ( <div> <h1>{country} - 省/州列表</h1> <ul> {states.map(state => ( <li key={state}> <Link href={`/${encodeURIComponent(country)}/${encodeURIComponent(state)}`}>{state}</Link> </li> ))} </ul> </div> ) } export function getStaticPaths() { const paths = Object.keys(regions).map(country => ({ params: { country } })) return { paths, fallback: false } } export function getStaticProps({ params }) { const country = params.country const states = Object.keys(regions[country]) return { props: { country, states } } }
3.3 省/州层级动态页 pages/[country]/[state]/index.js
预声明所有国家+州的组合参数:
// pages/[country]/[state]/index.js import Link from 'next/link' import { regions } from '../../../data/regions' export default function StatePage({ country, state, cities }) { return ( <div> <h1>{country} {state} - 城市列表</h1> <ul> {cities.map(city => ( <li key={city}> <Link href={`/${encodeURIComponent(country)}/${encodeURIComponent(state)}/${encodeURIComponent(city)}`}>{city}</Link> </li> ))} </ul> </div> ) } export function getStaticPaths() { const paths = [] Object.entries(regions).forEach(([country, states]) => { Object.keys(states).forEach(state => { paths.push({ params: { country, state } }) }) }) return { paths, fallback: false } } export function getStaticProps({ params }) { const { country, state } = params const cities = regions[country][state] return { props: { country, state, cities } } }
4. 验证构建效果
执行next build命令后,终端会输出所有预生成的页面,你可以看到所有国家页、省/州页、城市页都被标记为静态页面(显示○符号),访问时直接返回静态资源,不会触发服务端渲染逻辑。
提示:如果使用Next.js 13+ App Router,将getStaticPaths替换为对应路由段的generateStaticParams方法即可,逻辑完全一致。
内容的提问来源于stack exchange,提问作者financial_physician
相关产品推荐
相关产品推荐

