关于 incremental-static-rendering
面向 Next.js 开发者的增量静态生成指南,介绍如何在不重建整个网站的情况下,于后台新增和更新页面。
主要功能
- 01后台重新生成页面
- 02按需生成新路由
- 03按时间重新验证
- 04按需重新验证指导
适用场景
- 01无需整体重建即可更新博客文章
- 02扩展大型商品目录
- 03内容变更后刷新页面
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ patternsdev/ skills --skill incremental-static-rendering安装后在 Claude Code 中输入/incremental-static-rendering确认已加载。
详细介绍
增量静态生成
静态生成(SSG)解决了 SSR 和 CSR 的大部分问题,但适用于渲染以静态内容为主的页面。当要渲染的内容是动态的或频繁变化时,它就会受到限制。
想象一下,一个不断增长的博客有多篇文章。你肯定不想仅仅因为要更正其中一篇文章里的一个错字,就重新构建并部署整个网站。同样,新增一篇博客文章也不应该导致所有现有页面都需要重新构建。因此,单靠 SSG 不足以渲染大型网站或应用。
适用场景
- 当页面大多是静态的,且需要定期更新数据,但不需要完整重新构建时,可使用此方案
- 这适用于大型网站(博客、电商),因为每次发生更改都重新构建所有页面并不实际
不适用场景
- 当内容实时变化,且无法接受过时数据时(例如,实时比分、股票行情)
- 对于完全动态且按用户个性化的页面,SSR 是更合适的选择
- 当重新验证的时间窗口会造成体验混乱,使不同用户看到不同版本的内容时
说明
- 在
getStaticProps中使用revalidate,设置后台重新生成页面的时间间隔 - 在
getStaticPaths中使用fallback: true,在首次请求时延迟生成页面 - 考虑使用按需重新验证(
revalidatePath、revalidateTag),以便在内容更改后立即更新 - 在 Next.js 13+ App Router 中,使用
generateStaticParams和异步组件实现 ISR
详情
增量静态生成(iSSG)模式是对 SSG 的升级,旨在解决动态数据问题,并帮助静态网站扩展,以处理大量频繁变化的数据。iSSG 允许你在新页面请求不断到来的同时,在后台预渲染一部分页面,从而更新现有页面并添加新页面。
示例代码
iSSG 从两个方面实现增量更新:在网站构建完成后,为现有静态网站逐步引入更新。
- 允许添加新页面
- 允许更新现有页面,也称为增量静态“重新”生成
添加新页面
通过延迟加载的方式,在构建完成后将新页面加入网站。这意味着新页面会在首次请求时立即生成。生成过程中,可以在前端向用户显示备用页面或加载指示器。
export async function getStaticPaths() {
const products = await getProductsFromDatabase();
const paths = products.map((product) => ({
params: { id: product.id }
}));
// fallback: true means that the missing pages
// will not 404, and instead can render a fallback.
return { paths, fallback: true };
}
// params will contain the id for each generated page.
export async function getStaticProps({ params }) {
return {
props: {
product: await getProductFromDatabase(params.id)
}
}
}
export default function Product({ product }) {
const router = useRouter();
if (router.isFallback) {
return <div>Loading...</div>;
}
// Render product
}
这里我们使用了 fallback: true。如果某个特定产品对应的页面不可用,就会显示该页面的备用版本,例如上面的 Product 函数所示的加载指示器。同时,Next.js 会在后台生成该页面。生成完成后,页面会被缓存,并取代备用页面显示。之后的访客请求该页面时,系统会立即显示缓存版本。
更新现有页面
要重新渲染现有页面,需要为其设置合适的超时时间。这样,在设定的超时时间过去后,页面就会重新验证。在页面完成重新验证之前,用户会继续看到页面的旧版本。因此,iSSG 使用 stale-while-revalidate 策略:重新验证期间,用户会收到缓存版本或过时版本。重新验证完全在后台进行,无需完整重新构建。
// This function runs at build time on the build server
export async function getStaticProps() {
return {
props: {
products: await getProductsFromDatabase(),
revalidate: 60, // This will force the page to revalidate after 60 seconds
}
}
}
// The page component receives products prop from getStaticProps at build time
export default function Products({ products }) {
return (
<>
<h1>Products</h1>
<ul>
{products.map((product) => (
<li key={product.id}>{product.name}</li>
))}
</ul>
</>
)
}
在 getStaticProps() 函数中加入了 60 秒后重新验证页面的代码。收到请求时,系统会先提供可用的静态页面。每隔一分钟,系统会在后台使用新数据刷新静态页面。生成完成后,静态文件的新版本就会可用,并在接下来的一分钟内响应所有新请求。此功能适用于 Next.js 9.5 及更高版本。
优势
iSSG 不仅具备 SSG 的所有优势,还提供更多优势:
- 动态数据:无需重建网站即可支持动态数据。
- 速度:iSSG 至少和 SSG 一样快,因为数据检索和渲染仍在后台进行。客户端或服务端所需的处理很少。
- 可用性:用户始终可以在线访问任意页面的较新版本。即使后台重新生成失败,旧版本也会保持不变。
- 一致性:重新生成在服务端逐页进行,因此数据库和后端的负载较低,性能也保持稳定。因此,延迟不会出现峰值。
- 易于分发:与 SSG 网站一样,iSSG 网站也可以通过用于提供预渲染网页的 CDN 网络进行分发。