
Từ SSR đến Cache Components – Next.js đang thay đổi cách chúng ta nghĩ về Rendering
Table of Contents9 sections
"Trang này nên dùng SSR hay SSG?"
Đây từng là câu hỏi đầu tiên mình đặt ra mỗi khi bắt đầu một dự án Next.js.
Nếu dữ liệu ít thay đổi, mình sẽ chọn SSG.
Nếu cần dữ liệu mới theo từng request, mình sẽ chọn SSR.
Mọi thứ có vẻ rất rõ ràng.
Nhưng càng làm nhiều dự án, mình càng nhận ra một vấn đề:
Không có trang web nào hoàn toàn Static hoặc hoàn toàn Dynamic.
Một trang thương mại điện tử là ví dụ điển hình:

Trong đó:
Logo gần như không bao giờ thay đổi.
Banner chỉ cập nhật vài lần mỗi ngày.
Thông tin sản phẩm có thể cập nhật mỗi vài phút.
Giỏ hàng phụ thuộc vào từng người dùng.
Danh sách gợi ý được cá nhân hóa.
Rõ ràng, không phải tất cả đều có cùng mức độ "động".
Đó cũng là lý do Next.js đang dần thay đổi cách tiếp cận việc rendering.
Hành trình của Next.js
Nếu nhìn lại vài năm gần đây, có thể thấy Next.js liên tục tiến hóa.

Ban đầu chúng ta chỉ có hai lựa chọn:
Static Site Generation (SSG)
Server Side Rendering (SSR)
Sau đó React mang đến Streaming.
Tiếp theo là Partial Prerendering (PPR).
Và đến Next.js 16, trọng tâm dần chuyển sang Cache Components.
Vấn đề của SSG
SSG rất đơn giản.
HTML được tạo ngay từ lúc build.

Ưu điểm | Nhược điểm |
|---|---|
|
|
Ví dụ:
Trang sản phẩm giảm giá.
Nếu build lúc 8 giờ sáng thì đến 5 giờ chiều, giá hiển thị có thể đã không còn chính xác.
Vấn đề của SSR
SSR giải quyết vấn đề dữ liệu cũ.

Người dùng luôn nhận được dữ liệu mới nhất.
Nhưng đổi lại:
Mỗi request đều phải render lại toàn bộ trang.
Điều này tạo ra hai vấn đề.
Server phải làm nhiều việc hơn.
Người dùng phải chờ toàn bộ trang render xong mới thấy nội dung.
Nhưng một trang web đâu phải thứ gì cũng "động"
Đây là điểm mình thấy thú vị nhất.
Giả sử một trang sản phẩm.
Trong thực tế:
Thành phần | Có cần render mỗi request? |
|---|---|
Header | Không |
Hero Banner | Có thể |
Product Detail | Có thể |
Cart | Có |
Recommendation | Có |
Nếu Header không thay đổi, tại sao mỗi request vẫn phải render lại?
Đó chính là câu hỏi mà React Streaming và sau này là PPR cố gắng trả lời.
Streaming thay đổi trải nghiệm người dùng
Thay vì chờ tất cả dữ liệu:

React có thể gửi từng phần.

Người dùng không còn nhìn màn hình trắng trong vài giây.
Họ có cảm giác ứng dụng phản hồi gần như ngay lập tức.
Đó là sức mạnh của Streaming.
Partial Prerendering
PPR đưa ý tưởng này tiến thêm một bước.
Thay vì render toàn bộ trang động, Next.js tạo trước một Static Shell.

Người dùng nhìn thấy giao diện gần như ngay lập tức.
Sau đó từng phần động được stream vào.

Đây là lý do nhiều người nói rằng PPR giúp website vừa nhanh vừa luôn có dữ liệu mới.
Nhưng tại sao bây giờ mọi người lại nói về Cache Components?
Nếu đọc tài liệu Next.js mới, bạn sẽ thấy cái tên PPR xuất hiện ít hơn trước.
Thay vào đó là Cache Components.
Theo mình, đây là thay đổi về tư duy.
Trước đây chúng ta nghĩ:
Trang này là Static hay Dynamic?
Bây giờ chúng ta nghĩ:
Component này nên cache trong bao lâu?
Ví dụ:

Không còn khái niệm:
"Trang này dùng SSR."
hay
"Trang này dùng SSG."
Mỗi component đều có chiến lược riêng.
Điều này ảnh hưởng gì đến cách viết code?
Mình thấy cách đặt câu hỏi khi xây dựng component đã thay đổi.
Ngày trước:
Component này hiển thị gì?
Component này có props gì?
Bây giờ:
Dữ liệu này có thực sự cần mới ở mọi request không?
Có thể cache không?
Nếu cache thì trong bao lâu?
Có phụ thuộc vào người dùng hiện tại không?
Cache không còn là chuyện của CDN.
Nó trở thành một phần trong quá trình thiết kế UI.
Một ví dụ đơn giản
Giả sử có trang chi tiết sản phẩm.
export default function ProductPage() {
return (
<>
<Hero />
<Product />
<Cart />
<Recommendation />
</>
);
}Nếu tất cả đều phải render cùng lúc:

Người dùng phải chờ.
Nhưng nếu kết hợp Streaming:

Website sẽ mang lại cảm giác phản hồi nhanh hơn rất nhiều, dù tổng thời gian tải có thể không thay đổi quá nhiều.
Đây cũng là lý do các framework hiện đại ngày càng tập trung vào trải nghiệm hiển thị thay vì chỉ tối ưu thời gian render.
Kết luận
Có lẽ thay đổi lớn nhất của Next.js không phải là thêm một API mới.
Mà là thay đổi cách chúng ta suy nghĩ về việc render.
Ngày trước, câu hỏi thường là:
Nên dùng SSR hay SSG?
Ngày nay, câu hỏi có lẽ là:
Phần nào của giao diện thực sự cần động, và phần nào có thể cache?
Theo mình, đây là một hướng đi rất hợp lý.
Bởi trong thế giới thực, rất hiếm có trang web nào hoàn toàn Static hoặc hoàn toàn Dynamic.
Khi có thể tối ưu ở cấp độ component, chúng ta vừa giữ được hiệu năng, vừa đảm bảo dữ liệu luôn mới ở những nơi thực sự cần thiết.
Và có lẽ đó cũng chính là hướng mà Next.js sẽ tiếp tục theo đuổi trong những phiên bản sắp tới.