jvinhit//lab

Search posts

Type to search across journal entries.

navigate open esc close

Web Performance · Part 11 — Network & Caching

The network layer matters: HTTP caching (Cache-Control, ETag, immutable), CDN and edge, Brotli/Zstandard/Gzip compression, HTTP/2-3, and service-worker strategies for offline cache.

Request nhanh nhất là request không bao giờ xảy ra. Lớp mạng và caching quyết định bao nhiêu byte phải đi qua dây, từ đâu, và bao lâu một lần. Tối ưu tốt ở đây làm lần truy cập thứ hai gần như tức thì và giảm tải LCP/TTFB cho lần đầu.


1. HTTP Caching: trình duyệt tự nhớ tài nguyên

Trình duyệt cache tài nguyên dựa trên header server gửi. Header quan trọng nhất là Cache-Control.

Tài nguyên có hash (immutable)

Asset build ra với hash nội dung trong tên (app.a1b2c3.js) phải giữ nguyên nội dung tại URL đó — đổi nội dung thì đổi tên file. Có thể cache rất lâu:

Cache-Control: public, max-age=31536000, immutable

max-age=31536000 (1 năm) + immutable cho cache biết response không đổi trong thời gian còn fresh, kể cả khi reload. Lần sau trình duyệt có thể lấy asset từ memory/disk cache mà không revalidate; cache vẫn có thể bị eviction, nên “1 năm” không có nghĩa lưu vĩnh viễn.

HTML và tài nguyên hay đổi

HTML thường không nên fresh lâu trong browser (nếu không người dùng dễ thấy bản cũ). Dùng revalidation:

Cache-Control: no-cache
# no-cache does NOT mean "don't cache" — it means "cache but revalidate before use"

ETag & revalidation

ETag là validator của tài nguyên. Lần sau trình duyệt gửi If-None-Match: <etag>; nếu chưa đổi, server trả 304 Not Modified (không body) — tiết kiệm payload nhưng vẫn tốn round trip và response headers.

Chiến lược tổng quát: asset có hash → cache 1 năm immutable; HTML → no-cache (revalidate). Đây là nền của “lần đầu tải đủ, lần sau gần như tức thì”.


2. CDN & Edge

CDN đặt bản sao tài nguyên ở nhiều điểm (edge) gần người dùng địa lý. Lợi ích:

  • Giảm TTFB cho response cacheable: phục vụ từ edge gần thay vì origin server xa (ảnh hưởng LCP — Phần 5).
  • Giảm tải origin: edge xử lý phần lớn request tĩnh.
  • Edge compute: chạy logic nhẹ (A/B, redirect, personalization) ngay tại edge.

Static site (như blog này) rất hợp với CDN vì HTML/asset có thể cache ở edge. Với HTML động/cá nhân hóa, CDN chỉ giúp mạnh khi cache key, private/public, cookie và invalidation được cấu hình đúng.


3. Nén: Brotli, Zstandard & Gzip

Nén văn bản (HTML, CSS, JS, SVG, JSON) có thể giảm mạnh dung lượng truyền; tỷ lệ thực tế phụ thuộc nội dung và mức nén. Server chọn encoding từ Accept-Encoding của client:

  • Brotli (br): lựa chọn phổ biến cho asset text tĩnh, thường nén tốt hơn Gzip.
  • Zstandard (zstd): content coding hiện đại, giải nén nhanh và đã xuất hiện trong Accept-Encoding của nhiều browser mới; chỉ bật khi CDN/server thương lượng đúng và vẫn có fallback.
  • Gzip (gzip): fallback có độ phủ rất rộng.

Hầu hết CDN/host bật nén tự động; nếu tự cấu hình server, đảm bảo response biến thể theo Accept-Encoding (thường qua Vary) và có fallback. Đừng nén lại ảnh/video/zip đã nén — thường không lợi và còn tốn CPU.

Mẹo: với asset tĩnh, nén sẵn lúc build (pre-compress thành .br/.gz) để server chỉ việc gửi file đã nén, không nén lại mỗi request.


4. HTTP/2 & HTTP/3

Phiên bản giao thức ảnh hưởng cách request song song:

  • HTTP/1.1: thực tế thường chỉ có một response đang tiến triển trên mỗi kết nối, nên browser mở nhiều kết nối để song song hóa.
  • HTTP/2: multiplexing nhiều stream trên một kết nối, loại bỏ head-of-line blocking ở tầng HTTP; packet loss của TCP vẫn có thể làm mọi stream trên kết nối cùng chờ.
  • HTTP/3: HTTP chạy trên QUIC (trên UDP); các stream có loss recovery độc lập, nên mất packet ở một stream không chặn tất cả stream khác. QUIC cũng hỗ trợ connection migration tốt hơn khi đổi Wi-Fi/di động.

Hệ quả thực tế: với HTTP/2-3, gộp tất cả vào một file khổng lồ không còn cần thiết và có thể phá caching/code splitting. Nhưng hàng trăm chunk siêu nhỏ vẫn có overhead request, header và scheduling; hãy chia theo ranh giới route/tính năng hợp lý (Phần 8) và đo waterfall. Phần 19 đi sâu transport, TLS và caching nâng cao.


5. Service Worker: cache có lập trình

Service Worker là worker theo sự kiện nằm giữa trang và network; browser có thể khởi động/dừng nó giữa các event. Nó cho phép intercept request, phục vụ offline và kiểm soát Cache Storage. Dùng Workbox giúp tránh những lỗi dễ gặp như quên ghi network response vào cache:

// sw.ts — Workbox runtime caching for GET requests
import { registerRoute } from 'workbox-routing';
import { ExpirationPlugin } from 'workbox-expiration';
import { CacheFirst, NetworkFirst } from 'workbox-strategies';

registerRoute(
  ({ request, url }) =>
    request.method === 'GET' &&
    url.origin === self.location.origin &&
    url.pathname.startsWith('/assets/'),
  new CacheFirst({
    cacheName: 'assets-v1',
    plugins: [new ExpirationPlugin({ maxEntries: 100, maxAgeSeconds: 30 * 24 * 60 * 60 })],
  }),
);

registerRoute(
  ({ request, url }) =>
    request.method === 'GET' &&
    url.origin === self.location.origin &&
    url.pathname.startsWith('/api/public/'),
  new NetworkFirst({
    cacheName: 'public-api-v1',
    networkTimeoutSeconds: 3,
    plugins: [new ExpirationPlugin({ maxEntries: 50, maxAgeSeconds: 24 * 60 * 60 })],
  }),
);

Các chiến lược chính: cache-first (asset revisioned), network-first (nội dung cần tươi nhưng cho phép offline fallback), stale-while-revalidate (trả cache ngay rồi cập nhật nền). Luôn đặt cache name/version, giới hạn tuổi/số entry, và chỉ cache response phù hợp.

Cảnh báo: service worker mạnh nhưng phức tạp (vòng đời, cập nhật, cache cũ kẹt lại). Chỉ thêm khi cần offline/PWA hoặc cache nâng cao. Không cache API cá nhân hóa/nhạy cảm bằng policy chung; kiểm tra auth, tenant, logout và quota trước.


6. Giảm số lượng & kích thước request

  • Loại request thật sự thừa: bỏ dependency/asset không dùng; dùng SVG sprite khi nhiều icon được tái sử dụng, nhưng đừng gộp chỉ để giảm request trên HTTP/2-3.
  • Tránh redirect chain: mỗi redirect là một vòng mạng; trỏ thẳng URL cuối.
  • preconnect/dns-prefetch cho origin bên thứ ba quan trọng (Phần 4).
  • Phân trang/lazy dữ liệu lớn thay vì tải hết một lần.

7. Checklist network & caching

  1. Asset có hash đặt Cache-Control: immutable, max-age=1 năm?
  2. HTML đặt no-cache (revalidate) để không kẹt bản cũ?
  3. Phục vụ qua CDN để giảm TTFB toàn cầu?
  4. Bật Brotli/Zstandard cho client hỗ trợ và Gzip fallback (pre-compress asset tĩnh nếu hợp lý)?
  5. Dùng HTTP/2-3 (không gộp file thái quá)?
  6. Cần offline/PWA → service worker với chiến lược phù hợp (cẩn thận vòng đời)?
  7. Cắt redirect chain và request thừa?

Tóm tắt

  • Request nhanh nhất là request không xảy ra — caching là đòn bẩy lớn nhất ở lớp mạng.
  • Asset có hash: cache 1 năm immutable; HTML: no-cache revalidate; ETag cho 304.
  • CDN giảm TTFB cho response cacheable; Brotli/Zstandard/Gzip được thương lượng theo client; HTTP/2-3 giảm nhu cầu gộp file thái quá nhưng không xóa mọi overhead.
  • Service Worker (cache-first / network-first / stale-while-revalidate, qua Workbox) cho offline — dùng có ý thức vì vòng đời phức tạp.

Phần tiếp theo: Phần 12 khép chặng nền tảng bằng audit A–Z, performance budget và giám sát CI; Phần 13–22 tiếp tục với RUM và các chủ đề chuyên sâu.