Edge Computing 在前端領域越來越熱。作為架構負責人,最近做了幾個專案的渲染策略選型。整理一下不同場景下的決策邏輯。
渲染策略全景
靜態生成(SSG) → 構建時生成,CDN 快取,最快
增量靜態再生(ISR) → 按需生成 + 定期重新驗證
流式 SSR → 服務端渲染 + 流式傳輸
Edge SSR → 在 CDN 邊緣節點渲染
Edge Middleware → 邊緣節點做路由/鑑權/改寫
場景一:營銷頁面 → SSG + ISR
內容變化不頻繁的頁面,SSG 是最優解:
typescript
// next.config.js
module.exports = {
output: "export", // 純靜態
};
需要內容更新但不需要即時性的,用 ISR:
typescript
// app/marketing/[slug]/page.tsx
export async function generateStaticParams() {
const pages = await getCmsPages();
return pages.map((p) => ({ slug: p.slug }));
}
// 60秒後重新驗證,使用者看到的最多延遲 60 秒
export const revalidate = 60;
export default async function MarketingPage({
params,
}: {
params: { slug: string };
}) {
const page = await getPage(params.slug);
return <MarketingLayout page={page} />;
}
場景二:使用者儀表盤 → Edge SSR
個性化內容多、對首屏延遲敏感的場景:
typescript
// middleware.ts — Edge Runtime
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export function middleware(request: NextRequest) {
// 在邊緣節點做鑑權,不需要回源
const token = request.cookies.get("auth-token");
if (!token && request.nextUrl.pathname.startsWith("/dashboard")) {
return NextResponse.redirect(new URL("/login", request.url));
}
// 根據使用者地區選擇語言
const country = request.geo?.country || "CN";
const response = NextResponse.next();
response.headers.set("x-user-country", country);
return response;
}
export const config = {
matcher: ["/dashboard/:path*"],
};
typescript
// 配置 Edge Runtime
export const runtime = "edge";
場景三:電商商品頁 → Streaming SSR + Edge
商品資訊即時性要求高,但不同區塊優先順序不同:
tsx
// app/product/[id]/page.tsx
import { Suspense } from "react";
export default async function ProductPage({
params,
}: {
params: { id: string };
}) {
return (
<div>
{/* 核心資訊同步載入 */}
<ProductHeader id={params.id} />
{/* 評論延遲載入 */}
<Suspense fallback={<div>載入評論中...</div>}>
<ProductReviews id={params.id} />
</Suspense>
{/* 推薦商品延遲載入 */}
<Suspense fallback={<div>載入推薦中...</div>}>
<Recommendations id={params.id} />
</Suspense>
</div>
);
}
場景四:A/B 測試 → Edge Middleware
在邊緣節點分流,不影響後端邏輯:
typescript
// middleware.ts
import { NextResponse } from "next/server";
export function middleware(request: NextRequest) {
const bucket = Math.random() < 0.5 ? "control" : "variant-a";
const response = NextResponse.next();
response.cookies.set("ab-bucket", bucket, {
httpOnly: true,
maxAge: 60 * 60 * 24 * 30, // 30 天
});
// 根據 bucket 改寫到不同版本的頁面
if (bucket === "variant-a" && request.nextUrl.pathname === "/checkout") {
return NextResponse.rewrite(new URL("/checkout-v2", request.url));
}
return response;
}
選型決策樹
內容是否所有人一樣?
├── 是 → SSG
└── 否 → 內容變化頻率?
├── 低(分鐘級)→ ISR
├── 中(秒級)→ Streaming SSR
└── 高(即時)→ Edge SSR + WebSocket
是否需要邊緣處理(鑑權/分流/地理)?
├── 是 → Edge Middleware + 上述渲染策略
└── 否 → 普通 SSR 即可
成本考量
SSG: 構建成本高,執行成本極低(純 CDN)
ISR: 構建成本低,執行成本低(按需生成)
Edge SSR:執行成本中等(Edge Worker 計費)
Streaming SSR:執行成本中等(需要 Node.js 伺服器)
我們內部專案的經驗:90% 的頁面用 SSG/ISR,10% 的頁面用 Edge SSR。不要為了用 Edge 而用 Edge。
小結
- 內容不怎麼變 → SSG/ISR,成本最低
- 個性化 + 低延遲 → Edge SSR
- 分割槽塊優先順序 → Streaming SSR + Suspense
- 鑑權/分流/改寫 → Edge Middleware
- 不要過度工程化,按需選擇