Chương 3 — Triển khai & Đánh giá
Thực Nghiệm
Toàn bộ hệ thống được triển khai lên môi trường Internet thực tế trước khi đo lường. Không đo trên localhost. Công cụ: Google Lighthouse Desktop.
Mục 3.3.1
Triển khai hệ thống
Hosting
DigitalOcean VPS
Máy chủ ảo độc lập
Tài nguyên xử lý riêng biệt, phản ánh chính xác tốc độ thực tế của hệ thống. Không bị ảnh hưởng bởi các tenant khác.
Automation
Coolify
Tự quản lý trên VPS
Tương tự Vercel/Heroku nhưng tự cài trên VPS. Tự động kéo code mới, đóng gói Docker, và khởi chạy cả 3 phân hệ.
Domain
ie213saigonblog.online
HTTPS + SSL
Hệ thống đã được cấu hình định tuyến thành công và chạy chính thức dưới tên miền thực tế với SSL.
Coolify tự động hoá việc kéo mã nguồn mới nhất, đóng gói môi trường (Docker) và khởi chạy mượt mà cả 3 phân hệ: Frontend (Next.js), Backend (ExpressJS) và Cơ sở dữ liệu (MongoDB) — tất cả trên cùng một VPS duy nhất.
Mục 3.3.2 – 3.3.5
Kết quả đo lường Lighthouse
Lighthouse Performance: Xuất sắc
SI: ~0.6s · TTFB: ~10ms · FCP: ~0.4s · LCP: ~0.7s
Filmstrip Timeline (mô phỏng)
Sau khi gửi yêu cầu, trình duyệt đã nhận trang được build sẵn. Song song đó, hình ảnh là nội dung nặng nhất nên cần thêm thời gian để hiển thị.
TTFB
~10ms
Server response
FCP
~0.4s
First paint
LCP
~0.7s
Largest paint
SI
~0.6s
Speed Index
Nguyên nhân điểm cao
Trang đã được đóng gói thành file HTML tĩnh ngay tại npm run build. Máy chủ Next.js hoàn toàn không phải thực thi lệnh gọi API nào tới Backend khi người dùng truy cập — CDN phục vụ file tức thì.
Kết luận
Trang SSG cung cấp trải nghiệm tốc độ hoàn hảo nhất. Tuy nhiên, dữ liệu trên trang bị cố định — bài viết mới sau thời điểm Build không xuất hiện.
Đánh đổi: Dữ liệu đóng băng tại build time.
Lighthouse Performance: Xuất sắc
SI: ~0.6s · TTFB: ~10ms · FCP: ~0.4s · LCP: ~0.7s
Filmstrip Timeline (mô phỏng)
Sau khi gửi yêu cầu, trình duyệt đã nhận trang được build sẵn từ cache và chỉ cần chờ hình ảnh load vào trình duyệt.
TTFB
~10ms
Server response
FCP
~0.4s
First paint
LCP
~0.7s
Largest paint
SI
~0.6s
Speed Index
Nguyên nhân điểm cao
Tương tự SSG, ISR có các trang web đã được xây dựng sẵn thành file HTML hoàn chỉnh và máy chủ Next.js chỉ cần đưa nội dung qua cho người dùng. Nội dung luôn được cập nhật mới nhờ cơ chế on-demand revalidation qua webhook.
Kết luận
ISR là minh chứng rõ ràng nhất cho sự ưu việt của kiến trúc Hybrid. Phục vụ nội dung tĩnh ngay lập tức và chỉ âm thầm kết nối Backend để làm mới dữ liệu ở background.
Đánh đổi: Cần setup webhook endpoint, phức tạp hơn SSG.
Lighthouse Performance: Tốt
SI: ~1.8s · TTFB: ~300ms · FCP: ~0.8s · LCP: ~1.1s
Filmstrip Timeline (mô phỏng)
Sau khi gửi yêu cầu, trình duyệt phải đứng chờ máy chủ xử lý xong dữ liệu mới nhận được trang web. User thấy trắng trong thời gian server render.
TTFB
~300ms
Server response
FCP
~0.8s
First paint
LCP
~1.1s
Largest paint
SI
~1.8s
Speed Index
Nguyên nhân điểm bị giảm
Mỗi khi người dùng truy cập, máy chủ Next.js phải gọi API lấy dữ liệu từ Backend và tiến hành render HTML ngay tại thời điểm đó. Quá trình chờ dữ liệu này tạo ra độ trễ, làm chỉ số Speed Index bị kéo dài lên 1.8 giây.
Kết luận
SSR đảm bảo nội dung luôn mới nhất và chính xác ở thời gian thực. Tuy nhiên, tốc độ không còn tức thì và phụ thuộc hoàn toàn vào sức khỏe của máy chủ.
Đánh đổi: Tốc độ phụ thuộc vào server — traffic cao dẫn đến TTFB cao.
Lighthouse Performance: Tốt
SI: ~2.0s · TTFB: ~5ms · FCP: ~1.2s · LCP: ~2.1s
Filmstrip Timeline (mô phỏng)
Sau khi gửi yêu cầu, trình duyệt lập tức nhận phản hồi HTML rỗng nhưng vẫn chờ thời gian trình duyệt lấy dữ liệu từ server để hiển thị được.
TTFB
~5ms
Server response
FCP
~1.2s
First paint
LCP
~2.1s
Largest paint
SI
~2.0s
Speed Index
Nguyên nhân điểm bị giảm
Tương tự SSR, CSR cần thời gian xây dựng và lấy dữ liệu từ Server trước khi hiển thị nội dung hoàn chỉnh. Khác với SSR, CSR xây dựng dữ liệu hoàn toàn trên trình duyệt người dùng, giảm chi phí Server nhưng user phải nhìn màn hình loading.
Kết luận
Dù trang phản hồi khung giao diện nhanh (TTFB thấp), người dùng vẫn phải nhìn màn hình chờ một khoảng thời gian lâu trước khi thấy nội dung thực sự.
Đánh đổi: TTFB thấp nhưng gây hiểu nhầm — HTML rỗng, nội dung chưa có gì.
Mục 3.3.6
Tổng kết so sánh
| Mode | Score | TTFB | FCP | LCP | SI | Dữ liệu |
|---|---|---|---|---|---|---|
| SSG | 92/100 | ~10ms | ~0.4s | ~0.7s | ~0.6s | Đóng băng tại build |
| ISR | 92/100 | ~10ms | ~0.4s | ~0.7s | ~0.6s | On-demand qua webhook |
| SSR | 88/100 | ~300ms | ~0.8s | ~1.1s | ~1.8s | Realtime mỗi request |
| CSR | 88/100 | ~5ms | ~1.2s | ~2.1s | ~2.0s | Realtime, fetch tại browser |
Về tốc độ tải trang
SSG và ISR chiếm ưu thế tuyệt đối với 92/100 nhờ loại bỏ hoàn toàn server compute mỗi request. SSR và CSR cùng đạt 88/100, phải đánh đổi bằng độ trễ lấy và xử lý dữ liệu.
Về tính cập nhật dữ liệu
SSR và CSR đảm bảo real-time nhưng đánh đổi tốc độ. SSG nhanh nhất nhưng dữ liệu cố định. ISR là giải pháp tối ưu: tốc độ ngang SSG, cập nhật on-demand qua webhook mà không rebuild toàn bộ site.
Mục 3.4 — Phương pháp tối ưu khác
Tối ưu hiệu năng bổ sung
Mục 3.4.1
Tối ưu hình ảnh với Next/Image + Sharp
Hình ảnh thường chiếm phần lớn dung lượng tải xuống của một trang web. Đây là nơi dễ dàng cải thiện chỉ số LCP (Largest Contentful Paint) nhất.
Thẻ HTML
<img /> (truyền thống)Kết quả
Ảnh gốc kích thước đầy đủ
next.config.mjs — remotePatterns
images: {
remotePatterns: [{
protocol: 'https',
hostname: '*.digitaloceanspaces.com',
}]
}Cấu hình này cho phép Sharp lấy và xử lý ảnh an toàn từ DigitalOcean Spaces. Ảnh tự động nén và điều chỉnh kích thước cho phù hợp với màn hình.
priority={i === 0} trên ảnh hero đầu tiên của HomeSlider inject một thẻ<link rel="preload">vào <head> — browser fetch ảnh trước khi render component, cải thiện trực tiếp chỉ số LCP.
Mục 3.4.2
Tối ưu tốc độ lấy dữ liệu — Full Colocation
Nút thắt cổ chai lớn nhất trong SSR và CSR thường nằm ở tốc độ I/O giữa các phân hệ. Khi Frontend, Backend và Database đặt trên các máy chủ khác nhau, mỗi request phải truyền tải qua Internet công cộng — cộng dồn lại làm tăng mạnh TTFB.
❌ Phân tán (Distributed)
Tổng: 150–300ms mỗi request
✅ Colocation (Dự án này)
DigitalOcean VPS (SGP)
Giao tiếp qua localhost — không qua Internet
Tổng: ~19.8ms mỗi request
Terminal Coolify — curl đo thời gian truy vấn nội bộ
$ curl -w "\nConnect: %{time_connect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s" \
http://localhost:5123/api/posts/thao-cam-vien-sai-gon
Connect: 0.003618s (~3.6 ms)
TTFB: 0.019745s (~19.7 ms)
Total: 0.019798s (~19.8 ms)
Đây là yếu tố then chốt giúp các trang SSR và CSR trong đồ án đạt được tốc độ gần với trang tĩnh (SSG/ISR), đảm bảo trải nghiệm người dùng luôn mượt mà.
Mục 3.5 (Bổ sung)
On-demand ISR trong thực tế
So sánh trực quan SSG vs ISR
On-demand Revalidation trong thực tế
Minh hoạ: Admin chỉnh sửa tên bài viết từ "Thảo Cầm Viên Quận 1 HCM" → "Thảo Cầm Viên Quận 1 Hồ Chí Minh". Nhấn nút để mô phỏng webhook kích hoạt.
title:
"Thảo Cầm Viên Quận 1 HCM"
Không bao giờ thay đổi. Dù admin đã sửa, SSG vẫn hiển thị tên cũ cho đến khi npm run build.
title:
"Thảo Cầm Viên Quận 1 HCM"
Đang phục vụ bản cached. Chờ webhook từ backend...
Webhook Flow
Mục 3.5 — Mô phỏng thực tế
Áp dụng từng Rendering vào đúng vị trí
Thay vì áp dụng một kỹ thuật duy nhất cho toàn bộ dự án, mỗi trang nội dung được chỉ định một cơ chế kết xuất riêng biệt nhằm giải quyết các bài toán cụ thể về tốc độ, khả năng cập nhật dữ liệu và trải nghiệm người dùng.
Trang chủ & Bài viết
/ và /posts/[slug]Lý do lựa chọn
Nếu dùng SSG, nội dung trang chủ sẽ bị cố định. ISR giúp trang chủ vừa có tốc độ phản hồi nhanh, vừa đảm bảo SEO vượt trội và tự động cập nhật khi có bài viết mới.
Cơ chế vận hành
Khi admin thêm hoặc sửa bài viết, backend gửi webhook → Next.js regenerate trang ở background → user tiếp theo nhận bản mới mà không cần rebuild.
Trang thông tin tĩnh
/docs/hybrid, /docs/seo, ...Lý do lựa chọn
Các trang nội dung Footer như "Về chúng tôi" hay "Điều khoản" gần như không bao giờ thay đổi. SSG là phương án hiệu quả nhất — loại bỏ hoàn toàn việc gọi Backend hay truy vấn DB mỗi khi có người xem.
Cơ chế vận hành
Toàn bộ nội dung được biên dịch thành file HTML tĩnh một lần khi Build. Khi user nhấn link ở Footer, trình duyệt tải ngay file đã có sẵn trên CDN.
Trang Tìm kiếm
/search?q=...Lý do lựa chọn
Kết quả tìm kiếm phụ thuộc hoàn toàn vào từ khóa người dùng nhập tại thời điểm thực tế. Không thể dùng SSG hay ISR vì không thể xác định trước các tổ hợp tìm kiếm.
Cơ chế vận hành
Mỗi khi user tìm kiếm, yêu cầu gửi đến server. Next.js truy vấn DB, lấy danh sách bài viết khớp từ khóa và render thành HTML hoàn chỉnh trước khi gửi về trình duyệt.
Trang Quản trị
/admin/dashboardLý do lựa chọn
Trang admin chứa thông tin riêng tư và yêu cầu tính tương tác cao (thêm, xóa, sửa bài viết). Tối ưu SEO là không cần thiết — CSR tạo ra giao diện mượt mà như Desktop App.
Cơ chế vận hành
Browser tải bộ khung ứng dụng trống. JS gọi API lấy dữ liệu bài viết. Mọi thay đổi cập nhật trực tiếp trên giao diện ngay khi có phản hồi từ Backend mà không tải lại trang.
Tiếp theo
Chương 4: Kết quả & Kết luận
Tổng hợp số liệu đo lường, phân tích kết quả thực nghiệm và rút ra các kết luận về hiệu quả của 4 rendering mode trong môi trường Cloud