Next.js 13.5:静态生成商品页如何实现价格动态获取?
解决方案
方案1:使用客户端组件动态获取价格
这是最直接的实现方式——将价格展示部分封装为客户端组件,在浏览器端发起请求获取实时价格,完全不影响页面其余内容的静态生成逻辑。
步骤:
- 创建客户端组件
components/ProductPrice.jsx:
'use client'; import { useEffect, useState } from 'react'; export default function ProductPrice({ slug }) { const [price, setPrice] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchPrice = async () => { try { // 调用后端API获取对应商品的实时价格 const res = await fetch(`/api/products/${slug}/price`, { cache: 'no-store', // 禁用缓存,确保每次请求都拉取最新数据 }); if (!res.ok) throw new Error('Failed to fetch price'); const data = await res.json(); setPrice(data.price); } catch (err) { setError(err.message); } finally { setLoading(false); } }; fetchPrice(); }, [slug]); if (loading) return <span>Loading price...</span>; if (error) return <span>Error loading price: {error}</span>; return <span className="price">${price.toFixed(2)}</span>; }
- 在静态生成的页面组件
app/products/[slug]/page.jsx(默认是服务器组件)中引入该客户端组件:
import ProductPrice from '@/components/ProductPrice'; export async function generateStaticParams() { // 从数据库获取所有商品slug,用于构建阶段静态生成页面 const products = await fetch('/api/products', { cache: 'force-cache' }).then(res => res.json()); return products.map(product => ({ slug: product.slug })); } export default async function ProductPage({ params }) { // 获取商品静态信息(名称、描述等),强制缓存用于静态生成 const product = await fetch(`/api/products/${params.slug}`, { cache: 'force-cache' }).then(res => res.json()); return ( <div className="product-page"> <h1>{product.name}</h1> <p>{product.description}</p> {/* 价格由客户端组件动态实时获取 */} <ProductPrice slug={params.slug} /> {/* 其他静态内容 */} </div> ); }
- 编写对应的API路由
app/api/products/[slug]/price/route.js:
import { db } from '@/lib/db'; // 替换为你的数据库连接逻辑 export async function GET(request, { params }) { const { slug } = params; const product = await db.product.findUnique({ where: { slug }, select: { price: true }, }); if (!product) { return new Response(JSON.stringify({ error: 'Product not found' }), { status: 404 }); } return new Response(JSON.stringify({ price: product.price }), { headers: { 'Content-Type': 'application/json' }, }); }
方案2:服务器组件结合动态数据获取(需注意缓存策略)
如果不想依赖客户端组件,可以在服务器组件中单独对价格请求设置无缓存,但这会导致整个页面变为动态渲染(SSR)——其余静态内容仍会在构建时预取,但每次用户访问都会重新获取价格并渲染页面。
修改 app/products/[slug]/page.jsx:
export async function generateStaticParams() { const products = await fetch('/api/products', { cache: 'force-cache' }).then(res => res.json()); return products.map(product => ({ slug: product.slug })); } export default async function ProductPage({ params }) { // 静态信息使用强制缓存,构建时生成 const productStatic = await fetch(`/api/products/${params.slug}`, { cache: 'force-cache' }).then(res => res.json()); // 价格请求禁用缓存,每次访问都获取最新值 const productPrice = await fetch(`/api/products/${params.slug}/price`, { cache: 'no-store' }).then(res => res.json()); return ( <div className="product-page"> <h1>{productStatic.name}</h1> <p>{productStatic.description}</p> <span className="price">${productPrice.price.toFixed(2)}</span> </div> ); }
注意:这种方式会增加服务器负载,适合流量不大的场景,若流量较高建议优先选择方案1。
方案3:增量静态再生(ISR)(适合每日更新场景)
如果价格仅需每日更新,而非实时变更,可以使用ISR让页面在后台自动重新生成,既保留静态页面的性能优势,又能定期同步最新价格。
修改 page.jsx:
export async function generateStaticParams() { const products = await fetch('/api/products', { cache: 'force-cache' }).then(res => res.json()); return products.map(product => ({ slug: product.slug })); } // 设置页面每86400秒(24小时)自动重新生成一次 export const revalidate = 86400; export default async function ProductPage({ params }) { // 遵循revalidate缓存策略,24小时后自动重新获取数据 const product = await fetch(`/api/products/${params.slug}`).then(res => res.json()); return ( <div className="product-page"> <h1>{product.name}</h1> <p>{product.description}</p> <span className="price">${product.price.toFixed(2)}</span> </div> ); }
这种方式的局限性是价格更新存在延迟,无法满足实时获取最新价格的需求,仅适合固定周期更新的场景。
内容的提问来源于stack exchange,提问作者Andreas Oikon
相关产品推荐
相关产品推荐

