NextJS按需生成商品动态路由问题求助
问题描述
我正在使用NextJS为一个当前包含数千个商品且数量将大幅增长的数据库搭建前端,现有的site/products/路由运行正常。我希望添加一个查看单个商品的路由,例如site/products/{sku},创建动态路由组件后却持续出现404错误。经调研得知,动态路由需借助getStaticPaths和getStaticProps预渲染所有页面,但我不想每次执行npm run build时生成数千个页面,希望通过URL中的sku值调用API,在客户端或服务端动态生成页面并返回渲染后的HTML,请问该如何实现?我的思路是否有误?
可行方案
1. 增量静态再生(ISR)—— 推荐用于非实时数据
这种方式不需要在构建时预渲染所有页面,首次请求未生成的商品页面时,服务端会自动生成静态页面并缓存,后续请求直接返回缓存内容,还能按需更新缓存。
- 路由文件命名:Pages Router用
pages/products/[sku].js;App Router用app/products/[sku]/page.js - 核心配置:
getStaticPaths中设置fallback: 'blocking',getStaticProps添加revalidate参数控制缓存更新时间
Pages Router 示例代码:
export async function getStaticPaths() { return { paths: [], // 构建时不预渲染任何商品页面 fallback: 'blocking', // 首次请求未预渲染路径时,服务端生成页面 }; } export async function getStaticProps({ params }) { // 通过sku调用API获取商品数据 const res = await fetch(`https://your-api-domain.com/products/${params.sku}`); const product = await res.json(); // 商品不存在时返回404 if (!product) { return { notFound: true }; } return { props: { product }, revalidate: 3600, // 每3600秒(1小时)重新生成页面,可根据需求调整 }; } export default function ProductDetail({ product }) { return ( <div className="product-detail"> <h1>{product.name}</h1> <p>{product.description}</p> <span>价格:{product.price}</span> </div> ); }
2. 服务端渲染(SSR)—— 用于实时数据场景
每次用户访问商品页面时,服务端都会实时调用API获取数据并渲染HTML返回,适合商品数据频繁更新的场景。
- Pages Router中直接使用
getServerSideProps,无需配置getStaticPaths
Pages Router 示例代码:
export async function getServerSideProps({ params }) { const res = await fetch(`https://your-api-domain.com/products/${params.sku}`); const product = await res.json(); if (!product) { return { notFound: true }; } return { props: { product }, }; } export default function ProductDetail({ product }) { return ( <div className="product-detail"> <h1>{product.name}</h1> <p>{product.description}</p> <span>价格:{product.price}</span> </div> ); }
3. App Router(Next.js 13+)实现
Next.js 13+的App Router默认使用服务端组件,直接在页面组件中异步获取数据即可,无需额外的getServerSideProps/getStaticProps:
// app/products/[sku]/page.js async function fetchProduct(sku) { const res = await fetch(`https://your-api-domain.com/products/${sku}`, { // 实时获取数据:cache: 'no-store' // 或设置缓存时间:next: { revalidate: 3600 } cache: 'no-store', }); if (!res.ok) { throw new Error('商品不存在'); } return res.json(); } export default async function ProductPage({ params }) { const product = await fetchProduct(params.sku); return ( <div className="product-detail"> <h1>{product.name}</h1> <p>{product.description}</p> <span>价格:{product.price}</span> </div> ); }
如果需要客户端交互(比如添加购物车按钮),可以在组件顶部添加'use client'指令,搭配SWR/React Query做数据获取,但这种方式首屏不会返回渲染后的HTML,仅适合交互优先的场景。
关于你的思路
你的思路完全没问题,Next.js本身就支持无需全量预渲染的动态路由方案。之前的404错误大概率是因为getStaticPaths的fallback参数配置错误(比如设为false),或者路由文件命名不符合Next.js的动态路由规则(比如没加[sku]后缀)。
内容的提问来源于stack exchange,提问作者Amol Borkar

