部分預先渲染
注意: 部分預先渲染是一項實驗性功能,僅在 Canary 版本中提供,且可能會變更。尚未準備好用於生產環境。
部分預先渲染 (PPR) 可讓您在同一個路由中結合靜態和動態元件。
在建置期間,Next.js 會盡可能預先渲染路由。如果偵測到動態程式碼,例如從傳入的請求讀取,您可以將相關元件包裝在 React Suspense 邊界中。然後,Suspense 邊界的 fallback 將包含在預先渲染的 HTML 中。


🎥 觀看: 為什麼使用 PPR 以及其運作方式 → YouTube (10 分鐘)。
背景
PPR 使您的 Next.js 伺服器能夠立即傳送預先渲染的內容。
為了防止用戶端到伺服器的瀑布效應,動態元件在伺服器提供初始預先渲染的同時,開始從伺服器平行串流。這確保了動態元件可以在用戶端 JavaScript 在瀏覽器中載入之前開始渲染。
為了防止為每個動態元件建立許多 HTTP 請求,PPR 能夠將靜態預先渲染和動態元件組合到單個 HTTP 請求中。這確保了每個動態元件不需要多個網路往返。
使用部分預先渲染
漸進式採用 (Version 15 Canary 版本)
在 Next.js 15 Canary 版本中,PPR 作為實驗性功能提供。它在穩定版本中尚不可用。若要安裝
npm install next@canary
您可以透過在 next.config.js
中將 ppr
選項設定為 incremental
,並在檔案頂端匯出 experimental_ppr
路由設定選項,在版面配置和頁面中逐步採用部分預先渲染
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
experimental: {
ppr: 'incremental',
},
}
export default nextConfig
import { Suspense } from 'react'
import { StaticComponent, DynamicComponent, Fallback } from '@/app/ui'
export const experimental_ppr = true
export default function Page() {
return (
<>
<StaticComponent />
<Suspense fallback={<Fallback />}>
<DynamicComponent />
</Suspense>
</>
)
}
要知道:
- 沒有
experimental_ppr
的路由將預設為false
,並且不會使用 PPR 進行預先渲染。您需要為每個路由明確選擇加入 PPR。experimental_ppr
將適用於路由區段的所有子項目,包括巢狀版面配置和頁面。您不必將其新增至每個檔案,只需新增至路由的頂層區段即可。- 若要停用子區段的 PPR,您可以在子區段中將
experimental_ppr
設定為false
。
動態元件
在 next build
期間為您的路由建立預先渲染時,Next.js 要求動態 API 必須以 React Suspense 包裝。然後,fallback
會包含在預先渲染中。
例如,使用 cookies
或 headers
等函式
import { cookies } from 'next/headers'
export async function User() {
const session = (await cookies()).get('session')?.value
return '...'
}
此元件需要查看傳入的請求以讀取 Cookie。若要將其與 PPR 一起使用,您應該使用 Suspense 包裝元件
import { Suspense } from 'react'
import { User, AvatarSkeleton } from './user'
export const experimental_ppr = true
export default function Page() {
return (
<section>
<h1>This will be prerendered</h1>
<Suspense fallback={<AvatarSkeleton />}>
<User />
</Suspense>
</section>
)
}
元件僅在存取值時才選擇加入動態渲染。
例如,如果您從 page
讀取 searchParams
,您可以將此值作為 prop 轉發到另一個元件
import { Table } from './table'
export default function Page({
searchParams,
}: {
searchParams: Promise<{ sort: string }>
}) {
return (
<section>
<h1>This will be prerendered</h1>
<Table searchParams={searchParams} />
</section>
)
}
在表格元件內部,從 searchParams
存取值會使元件動態執行
export async function Table({
searchParams,
}: {
searchParams: Promise<{ sort: string }>
}) {
const sort = (await searchParams).sort === 'true'
return '...'
}
這有幫助嗎?