Static vs dynamic rendering năm 2026: chọn mode nào?
Cuộc tranh luận SSG-vs-SSR đã lỗi thời. Sáu rendering mode bao phủ toàn bộ phổ — đây là mode nào phù hợp với use case của bạn, kèm benchmark và code.
Bởi Ethan
2.293 từ · 12 phút đọc
Với hầu hết ứng dụng web mới, hãy dùng PPR với Cache Components trong Next.js 16. Với site nặng về nội dung mà không cần nhiều React, dùng Astro Server Islands. Dành Edge SSR trên Cloudflare Workers cho dự án Astro và auth middleware — không phải cho workload Next.js SSR nặng, nơi nó chạy chậm hơn Vercel Fluid 3.55×.
Câu hỏi “static vs dynamic” là câu hỏi sai. Năm 2026, bạn đang chọn giữa sáu rendering mode. Câu trả lời đúng phụ thuộc vào ngân sách TTFB, yêu cầu độ tươi mới của dữ liệu, và mức độ phức tạp bạn có thể chấp nhận.
Bài này dành cho ai
Frontend và full-stack engineer đang chọn chiến lược rendering cho ứng dụng mới, hoặc đang cân nhắc migrate ứng dụng hiện có. Nếu bạn đang xây CRUD admin panel không bao giờ cần SEO, CSR là câu trả lời và phần còn lại của bài này không dành cho bạn.
Nội dung bài viết
Sáu rendering mode — SSG, ISR, Streaming SSR, PPR/Cache Components, Edge SSR trên Cloudflare Workers, và Astro Server Islands — với profile TTFB thực tế, đặc điểm caching, và workload nơi mỗi mode tỏa sáng. Benchmark lấy từ nguồn chính: benchmark Vercel Fluid Compute đã được ghi chép, case study RSC streaming 2026 của SitePoint (có paywall), benchmark SSR 6 framework của Enterspeed, và chương performance của Web Almanac 2024. Phiên bản: Next.js 16.2, Astro 5, Cloudflare Workers (tháng 5 năm 2026).
Sáu rendering mode
1. SSG — static site generation
TTFB: ~20ms (CDN-cached)
Độ tươi dữ liệu: Chỉ lúc build
Độ phức tạp: Thấp
Trang được build lúc deploy và phục vụ từ CDN. Không có server nào tham gia xử lý request. Đây là lựa chọn tốt nhất cho docs, trang marketing, và blog có nội dung thay đổi hàng ngày hoặc hàng tuần.
Giới hạn mang tính cơ học: bạn chỉ có thể phục vụ những gì đã build. Một catalog 50.000 sản phẩm với inventory real-time không thể dùng SSG mà không chấp nhận dữ liệu cũ.
2. ISR — incremental static regeneration
TTFB: ~20ms (CDN hit)
Độ tươi dữ liệu: Tức thì khi publish (với on-demand invalidation)
Độ phức tạp: Trung bình
ISR là SSG có thêm background revalidation hook. Pattern được ưa chuộng năm 2026 là on-demand tag revalidation qua revalidateTag, không phải theo khoảng thời gian cố định. Khi sản phẩm thay đổi, webhook CMS gọi endpoint revalidation của bạn; CDN phục vụ nội dung mới trên request tiếp theo.
Đây là điểm ngọt cho e-commerce: TTFB từ CDN trên trang được cache, gần như tươi ngay sau publish. Bẫy chính là cache poisoning — nếu webhook revalidation kích hoạt khi lưu bản nháp thay vì khi publish, người đọc sẽ thấy nội dung chưa công bố.
3. Streaming SSR
TTFB: 40–90ms first bytes
Độ tươi dữ liệu: Real-time
Độ phức tạp: Trung bình
React 19 + Suspense gửi shell của trang ngay lập tức, sau đó stream các phần động khi dữ liệu sẵn sàng. Trong case study RSC 2026 của SitePoint (có paywall — URL trả về HTTP 403), điều này giảm TTFB từ 450ms xuống 45ms và LCP từ 1.2s xuống 380ms. Shell nhanh; phần còn lại theo sau.
Câu chuyện caching yếu hơn SSG hoặc PPR. Shell không thể CDN-cacheable theo cách một asset tĩnh hoàn toàn — bạn vẫn phải đến origin mỗi request để mở stream. Phù hợp cho social feed và dashboard cá nhân hóa; không đáng kiến trúc phức tạp cho trang chủ yếu là static.
4. PPR / Cache Components — mặc định hiện đại được khuyến nghị
TTFB: 20–80ms (CDN shell, p75)
Độ tươi dữ liệu: Shell vô thời hạn; phần động real-time
Độ phức tạp: Trung bình
Partial Pre-Rendering đã stable trong Next.js 16 (phát hành ngày 21 tháng 10 năm 2025). Flag experimental.ppr đã bị xóa. Kích hoạt bằng cacheComponents: true trong next.config.ts. Directive use cache stable trong Next.js 16.2.
Để xem đầy đủ câu chuyện nâng cấp — bao gồm cú lật caching model hay gây bất ngờ nhất — đọc đánh giá Next.js 16 của chúng tôi.
Model của PPR: shell trang được pre-render và CDN-cached như SSG, trong khi các phần động bên trong boundary <Suspense> stream real-time từ origin. Shell mang lại TTFB từ CDN — cùng tốc độ với SSG — trong khi các phần động fetch dữ liệu mới mỗi request. Bạn có tốc độ CDN cho phần lớn trang và dữ liệu real-time ở nơi cần.
Đây là cách nó trông ở tầng component:
// app/product/[id]/page.tsx — Next.js 16.2+
import { Suspense } from 'react'
import { ProductDetails } from './ProductDetails'
import { LiveInventory } from './LiveInventory'
// This component renders as a static CDN-cached shell
export default function ProductPage({ params }: { params: { id: string } }) {
return (
<main>
<ProductDetails id={params.id} />
{/* This boundary streams from origin at request time */}
<Suspense fallback={<div>Loading inventory…</div>}>
<LiveInventory id={params.id} />
</Suspense>
</main>
)
}
// ProductDetails.tsx — eligible for CDN caching
'use cache'
export async function ProductDetails({ id }: { id: string }) {
const res = await fetch(`/api/products/${id}`)
const data = await res.json()
return <h1>{data.name}</h1>
}
// LiveInventory.tsx — real-time, bypasses CDN cache
export async function LiveInventory({ id }: { id: string }) {
const res = await fetch(`/api/inventory/${id}`, { cache: 'no-store' })
const { available, eta } = await res.json()
return <p>{available} in stock — ships {eta}</p>
}
Directive 'use cache' trên ProductDetails báo cho Next.js biết component này có thể pre-render và phục vụ từ CDN vô thời hạn. LiveInventory không dùng cache và gọi origin mỗi request. Cả hai component dùng chung trang, URL, và shell CDN nhanh.
Nếu bạn bắt đầu ứng dụng Next.js mới năm 2026, đây là baseline.
5. Edge SSR — Cloudflare Workers
TTFB: 8–25ms (PoP gần nhất)
Độ tươi dữ liệu: Real-time
Độ phức tạp: Cao
Cloudflare Workers phân tán server của bạn qua 300+ point of presence với cold start dưới 1ms. Với người dùng toàn cầu, bạn có thể đạt TTFB 8–25ms — nhanh hơn hầu hết cấu hình origin-server cho nội dung động.
Có một cảnh báo đã được ghi nhận: Edge SSR không phải thắng lợi toàn diện cho Next.js SSR nặng. Trong benchmark 100 lần lặp của Vercel, Next.js SSR trên Cloudflare Workers đạt 1.895s so với 0.534s trên Vercel Fluid — chậm hơn 3.55×. V8 isolate runtime của Workers đặt ra chi phí thực sự cho các render Next.js tốn bộ nhớ. Web Almanac 2024 cũng ghi nhận: trang server-rendered đạt ~60% điểm “LCP tốt” so với ~45% cho CSR, nhưng khoảng cách đó thu hẹp khi so sánh edge deployment được tối ưu với infrastructure tương đương.
Điểm ngọt thực sự của Cloudflare Workers:
- Dự án Astro với template nhẹ
- Auth middleware và kiểm tra cookie tại edge
- A/B testing và phân tách traffic tại PoP
- Stack Cloudflare-native dùng D1, KV, và R2
Để so sánh chi phí và giới hạn bộ nhớ giữa Workers và Vercel Functions, xem Cloudflare Workers vs Vercel Functions.
Một Worker tối giản trông như sau:
// worker.js — serving region-specific content from KV
export default {
async fetch(request, env) {
const country = request.cf?.country ?? 'US'
const content =
(await env.CONTENT_KV.get(`landing:${country}`)) ??
(await env.CONTENT_KV.get('landing:US'))
return new Response(content, {
headers: { 'Content-Type': 'text/html;charset=UTF-8' },
})
},
}
Workers tỏa sáng ở đây vì KV lookup nằm ngay ở PoP. Không có round-trip về origin. Cảnh báo Next.js nặng không áp dụng khi logic render nhẹ như thế này.
Đừng chọn Workers vì “edge = nhanh.” Hãy chọn khi bạn thực sự cần phân tán toàn cầu với runtime nhẹ.
6. Astro Server Islands
TTFB: ~20ms (CDN shell)
Độ tươi dữ liệu: Theo island, on demand
Độ phức tạp: Trung bình
Astro 5 (tháng 12 năm 2024) đưa Server Islands lên stable. Model: trang hoàn toàn static phục vụ từ CDN với các component server:defer opt-in render từ server khi có request. Không có chi phí React runtime cho phần tĩnh chiếm đa số. Benchmark Enterspeed đặt Astro ở 0.8s LCP — ngang ngửa SSG — trong khi hỗ trợ cá nhân hóa theo từng request. Nếu bạn đang cân nhắc giữa Astro và Next.js ở cấp framework, Next.js vs Astro 2026 có so sánh chi tiết.
---
// src/pages/product/[id].astro
import ProductHero from '../components/ProductHero.astro'
import UserRecommendations from '../components/UserRecommendations.astro'
const { id } = Astro.params
---
<html>
<body>
<!-- Static: pre-built, served from CDN, zero JS weight -->
<ProductHero {id} />
<!-- Server Island: renders from origin on request -->
<UserRecommendations {id} server:defer>
<div slot="fallback">Loading recommendations…</div>
</UserRecommendations>
</body>
</html>
UserRecommendations stream vào sau shell phục vụ từ CDN. Phần còn lại của trang đã render xong. Nếu bạn thêm tương tác dựa trên React cho một island, bạn chỉ trả chi phí React bundle cho island đó — không phải cho toàn trang.
Phù hợp nhất: content site (media, docs, marketing) nơi phần lớn trang thực sự static nhưng bạn cần các phần theo user như trạng thái đăng nhập, gợi ý, hoặc số lượng giỏ hàng.
Ma trận quyết định
| Mode | TTFB | Khả năng cache | Độ tươi dữ liệu | Độ phức tạp | Phù hợp nhất |
|---|---|---|---|---|---|
| SSG | ~20ms (CDN) | ★★★★★ | Lúc build | Thấp | Docs, marketing, blog |
| ISR (on-demand) | ~20ms (CDN hit) | ★★★★★ | Tức thì khi publish | Trung bình | E-commerce, CMS-driven |
| Streaming SSR | 40–90ms first bytes | ★★ (shell only) | Real-time | Trung bình | Social feed, dashboard |
| PPR / Cache Components | 20–80ms (CDN shell) | ★★★★ | Shell: ∞ / Phần động: real-time | Trung bình | Mặc định hiện đại |
| Edge SSR (CF Workers) | 8–25ms (PoP) | ★★★ (PoP-local) | Real-time | Cao | App Astro toàn cầu, auth middleware |
| Server Islands (Astro 5) | ~20ms (CDN shell) | ★★★★★ | Theo island, on demand | Trung bình | Content site + cá nhân hóa |
| CSR | ~50ms (app shell) | ★★★ (app shell) | Real-time | Thấp–Trung bình | Admin panel, công cụ nội bộ |
Kết luận
Ứng dụng Next.js mới: Dùng PPR với Cache Components làm mặc định. Đặt cacheComponents: true, đánh dấu component chậm hoặc cá nhân hóa với 'use cache' hoặc { cache: 'no-store' }, bọc các phần động trong <Suspense>. Bạn có CDN TTFB cho shell và dữ liệu real-time ở nơi cần.
Catalog e-commerce ở quy mô lớn: ISR với on-demand revalidateTag invalidation. CDN phục vụ phiên bản cached nhanh; webhook CMS invalidate khi publish. Bạn có TTFB ở mức CDN mà không cần rebuild 50.000 trang mỗi lần thay đổi nội dung.
Site nặng về nội dung, không cần nhiều React: Astro Server Islands. Không trả chi phí React runtime cho nội dung static. Chỉ trả cho island cần tương tác hoặc cá nhân hóa.
Phân tán edge toàn cầu: Cloudflare Workers cho Astro hoặc template nhẹ. Không dành cho Next.js SSR nặng — khoảng cách hiệu năng 3.55× đã được ghi nhận và chưa bị bác bỏ.
Admin panel và dashboard nội bộ: CSR. SEO không phải yếu tố, dữ liệu vốn dĩ theo từng user, app shell cache ổn.
Chọn SSG nếu nội dung nhỏ và ổn định. Chọn ISR khi catalog lớn và CMS push khi publish. Chọn Streaming SSR khi trang chủ yếu là dữ liệu real-time cá nhân hóa mà không có shell static hữu ích. Chọn PPR cho mọi thứ ở giữa — đó là hầu hết ứng dụng.
Sự phân đôi cũ là cách nói ngắn gọn hữu ích vào năm 2021. Năm 2026, PPR là sự hội tụ thực tế của tốc độ static và dữ liệu real-time. Bắt đầu từ đó, rút lui về mode đơn giản hơn nếu độ phức tạp không được biện minh.
Lưu ý
ISR ở quy mô catalog lớn (100K+ trang với tag invalidation tích cực) chưa được toolchew benchmark — pattern mô tả ở đây là hành vi Next.js đã được ghi nhận và hướng dẫn Vercel đã công bố, không phải số liệu toolchew đo lường.
Số liệu từ case study Streaming SSR (TTFB 450ms → 45ms, LCP 1.2s → 380ms) đến từ báo cáo SitePoint 2026, không phải bài test của toolchew. URL SitePoint trả về HTTP 403 và không thể xác minh độc lập — số liệu được ghi ở đây với cảnh báo đó và nguồn được ghi chú là có paywall.
Benchmark Vercel Fluid vs Cloudflare Workers (0.534s vs 1.895s) được thực hiện bởi Vercel, đơn vị có lợi ích thương mại trong việc Fluid trông tốt. Phương pháp đã được ghi nhận và kết quả chưa bị bác bỏ một cách đáng tin cậy từ bên ngoài, nhưng hãy coi đó là một data point — không phải audit độc lập.
Liên kết affiliate: cả Vercel và Cloudflare đều được đề xuất trong bài này vì chất lượng thực sự. Vercel cho PPR và Next.js SSR nặng. Cloudflare cho edge toàn cầu với Astro. Kết luận sẽ không thay đổi dù cả hai không có chương trình affiliate.
Tham khảo
- Next.js 16 release blog — ngày 21 tháng 10 năm 2025
- Next.js Caching docs v16.2.6 — tháng 5 năm 2026
- Astro Server Islands docs (Astro 5)
- Vercel Fluid Compute benchmark
- Cloudflare Workers Cache API docs
- Web Almanac 2024 Performance
- Enterspeed: 6-framework SSR benchmark
- SitePoint: RSC Streaming Performance 2026 — có paywall