Next.js 渲染模型
Next.js 渲染模型演进
- PPR 预渲染,Partial Pre-Rendering
- SSR 服务器端渲染,v1 引入
- SSG 静态站点生成,v9.3 引入
- ISR 增量静态再生,v9.5 引入
PPR
配置:
// next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
// ppr: true 表示所有页面都是 PPR 的目标
// ppr: "incremental" 表示只有设置了 export const experimental_ppr = true 的 Route 为 PPR 的目标
ppr: "incremental", // ppr: boolean | "incremental"
},
};
export default nextConfig;
// page.tsx(layout.tsx 也可)
export const experimental_ppr = true;
export default function Page() {
// ...
}
APP Router 登场后
在 v13 发布的 APP Router 引入了 RSC(React 服务器组件)、服务器 Actions、多层缓存等多项篇章性质的改变
App Router 基本上支持 SSR/SSG/ISR 相当的功能,单不再用其区分,而是采用了静态渲染和动态渲染这两个概念来解释许多功能。
- 静态渲染:对应于传统的 SSG 或 ISR,在 build 时或执行 revalidate 后进行渲染
- 无 revalidate:相当于 SSG
- 有 revalidate:相当于 ISR
- 动态渲染:对应于传统的 SSR,每次请求时渲染
在 Pages Router 中,是在 build 时通过执行函数来决定使用 SSG 还是 ISR,因此是静态决定的。但在 App Router 中,通过 revalidatePath 或 revalidateTag 可以动态进行 revalidate,因此 SSG 与 ISR 不再是静态决定的。这或许是不再使用这些术语的原因之一。
通过 Cache Handler 可以选择缓存的持久化位置,参考
Streaming SSR
App Router 的 SSR 支持 Streaming SSR。
Streaming SSR 允许将页面渲染的部分通过 <Suspense> 延迟渲染,随着渲染的完成,结果会逐渐被发送给客户端。
import { Suspense } from "react";
import { PostFeed, Weather } from "./Components";
export default function Posts() {
return (
<section>
<Suspense fallback={<p>Loading feed...</p>}>
<PostFeed />
</Suspense>
<Suspense fallback={<p>Loading weather...</p>}>
<Weather />
</Suspense>
</section>
);
}
在上述实现例中,首先显示 fallback(Loading feed… 或 Loading weather…),当服务器端 <PostFeed> 或 <Weather> 的渲染完成后,渲染结果逐渐发送给客户端,fallback 被替换。这是一个在单个 HTTP 响应中完成的过程,响应的 HTML 包含 <PostFeed> 或 <Weather> 的 HTML,从 SEO 角度也进行了优化,这是一个重要特性。
SSG/SSR 中的静态与动态数据混合
构成页面所需的数据中,可能会混合有静态数据(可缓存)和动态数据(不可缓存)。例如,在电子商务网站中,商品信息本身可以在构建时或每次 revalidate 时获取并缓存,但登录信息无法缓存,需要动态获取。
在这种静态与动态数据混合的情况下,App Router 主要有以下两种实现模式:
- SSG+Client fetch:页面使用 SSG,客户端动态获取数据
- Streaming SSR:利用缓存(Data Cache)加速静态数据,同时使用
<Suspense>延迟渲染页面的一部分
优缺点:(TTFB 是 Time to First Bytes 的缩写)
与常规的 SSR 相比,Streaming SSR 可以改善 TTFB(首字节时间),但是仅返回静态文件的 SSG 显然更有优势。
从实现的角度来看,Client fetch 需要客户端处理和服务器端端点的连接处理(API Routes、tRPC、GraphQL 等),因此作者认为 Streaming SSR 更为简单。另外,Streaming SSR 由于 HTTP 的往返只需一次,因此可以认为动态元素显示的时间会更短,这一点从性能的角度也是值得评价的。
因此,Streaming SSR 虽然拥有许多优势,但无法获得 SSG 所具有的 TTFB 的速度,这是其权衡之处。作为解决这一问题的手段,出现了本文的主题 PPR。
PPR 是什么
PPR 是进一步发展的 Streaming SSR 技术,可以同时进行页面的 static rendering 和部分的 dynamic rendering。这是一种渲染模型,可以将 SSG/ISR 页面的一部分与 SSR 部分结合起来,或者将 Streaming SSR 的骨架部分转换为 SSG/ISR。