概览PPR 通过在 React Server Components 中使用 Suspense 包裹动态数据,使页面的静态部分可提前生成并缓存,动态部分在到达后以流式方式填充。该策略提升首屏与交互稳定性,适合列表壳体 + 动态详情等场景。页面结构与策略app/products/[id]/page.tsxexport const dynamic = 'force-static'
import { Suspense } from 'react'
export default async function ProductPage({ params }: { params: { id: string } }) {
return (
<div>
<Shell id={params.id} />
<Suspense fallback={<ReviewsSkeleton />}>
{/* 动态插槽:在数据就绪时填充 */}
{/* @ts-expect-error RSC */}
<Reviews id={params.id} />
</Suspense>
</div>
)
}
动态组件(RSC)// app/products/[id]/Reviews.tsx
export default async function Reviews({ id }: { id: string }) {
const data = await fetch(`https://api.example.com/reviews/${id}`, {
next: { revalidate: 300, tags: ['reviews'] },
}).then((r) => r.json())
return (
<ul>
{data.items.map((it: any) => (
<li key={it.id}>{it.content}</li>
))}
</ul>
)
}
Streaming 与缓存// app/products/[id]/Shell.tsx
export default function Shell({ id }: { id: string }) {
return (
<section>
<h1>产品 {id}</h1>
<p>静态外壳内容可被长时间缓存</p>
</section>
)
}
// 骨架
export function ReviewsSkeleton() {
return <p>评论加载中…</p>
}
治理要点使用 `dynamic = 'force-static'` 将页面外壳静态化;对必须动态的 Route 使用 `dynamic = 'force-dynamic'`。将动态区块包裹在 Suspense,以流式填充减少首屏等待。结合缓存标签(`tags`)进行局部失效,避免全页重渲染。对错误场景提供 `error.tsx` 与边界,以避免流式失败影响整体体验。验证与指标浏览器:Chrome 120+、Safari 17+、Firefox 120+Next.js:15.0+;Node.js:20.x;RSC 与 Streaming:稳定首屏可感知时间显著降低;动态评论在 1–3s 内填充

发表评论 取消回复