如何避免Next.js getStaticProps重复获取数据以提升性能
优化Next.js畅销产品数据重复请求的方案
针对所有产品页面重复请求相同畅销产品数据的问题,给你几个实用的优化思路:
1. 在_app.jsx中统一获取并传递数据
_app.jsx是所有页面的入口组件,你可以在这里一次性获取畅销产品数据,再通过props传递给所有子页面(包括[product_id].jsx),避免每个页面单独请求。
具体实现:
修改_app.jsx,添加数据获取逻辑:
// _app.jsx function MyApp({ Component, pageProps, bestSellingProducts }) { return <Component {...pageProps} bestSellingProducts={bestSellingProducts} />; } export async function getServerSideProps() { // 仅在此处请求一次畅销产品数据 const res = await fetch('你的后端接口地址'); const bestSellingProducts = await res.json(); return { props: { bestSellingProducts, }, }; } export default MyApp;
然后在[product_id].jsx中直接使用传递过来的props,无需重复请求:
// [product_id].jsx export default function ProductPage({ product, bestSellingProducts }) { // 直接使用bestSellingProducts return ( <div> {/* 产品内容区域 */} <section> <h2>畅销产品</h2> {/* 渲染畅销产品列表 */} </section> </div> ); } // 仅获取当前产品的专属数据 export async function getServerSideProps(context) { const { product_id } = context.params; const res = await fetch(`你的后端接口/products/${product_id}`); const product = await res.json(); return { props: { product, }, }; }
2. 给数据请求添加缓存逻辑
如果不想在_app.jsx中统一处理,可以在获取畅销产品的函数里加入缓存,让服务器复用已请求过的数据。
方式一:Node.js内存缓存
// [product_id].jsx // 全局变量存储缓存数据,仅在服务器端生效 let cachedBestSelling = null; let cacheExpireTime = 0; async function getBestSellingProducts() { const now = Date.now(); // 设置缓存有效期(示例为1小时),过期后重新请求 if (cachedBestSelling && now < cacheExpireTime) { return cachedBestSelling; } const res = await fetch('你的后端接口地址'); const data = await res.json(); cachedBestSelling = data; cacheExpireTime = now + 3600 * 1000; // 1小时后过期 return data; } export async function getServerSideProps(context) { const productRes = await fetch(`你的后端接口/products/${context.params.product_id}`); const product = await productRes.json(); // 调用带缓存的函数 const bestSellingProducts = await getBestSellingProducts(); return { props: { product, bestSellingProducts, }, }; }
方式二:Next.js内置fetch缓存(Next.js 12+)
Next.js的fetch默认支持缓存,通过配置参数可以直接复用请求结果:
async function getBestSellingProducts() { const res = await fetch('你的后端接口地址', { next: { revalidate: 3600 }, // 1小时后自动重新验证缓存 }); return res.json(); }
这种方式下,服务器会自动缓存请求结果,后续相同请求直接返回缓存数据,直到过期时间触发重新请求。
3. 静态生成场景下预取数据
如果你的产品页面是用getStaticProps静态生成的,可在生成页面时复用缓存的畅销产品数据:
// [product_id].jsx let cachedBestSelling = null; export async function getStaticProps(context) { // 首次请求后缓存数据,后续所有产品页面复用 if (!cachedBestSelling) { const res = await fetch('你的后端接口地址'); cachedBestSelling = await res.json(); } const productRes = await fetch(`你的后端接口/products/${context.params.product_id}`); const product = await productRes.json(); return { props: { product, bestSellingProducts: cachedBestSelling, }, revalidate: 86400, // 可选,设置页面重新生成间隔 }; } export async function getStaticPaths() { // 生成所有产品页面的路径 const res = await fetch('你的后端接口/products'); const products = await res.json(); const paths = products.map(product => ({ params: { product_id: product.id.toString() }, })); return { paths, fallback: 'blocking' }; }
这种方式在静态生成所有产品页面时,只会发起一次畅销产品数据请求,所有页面共享该缓存。
内容的提问来源于stack exchange,提问作者Ali Afzali
相关产品推荐
相关产品推荐

