Web Performance

Server Push (HTTP/2)

Tính năng HTTP/2 cho phép máy chủ gửi tài nguyên trước khi client yêu cầu, nhưng đã bị loại bỏ trong HTTP/3.

3 lượt xem Cập nhật: 01/06/2026

Server Push (HTTP/2) là gì?

Server Push là một tính năng của giao thức HTTP/2 cho phép máy chủ gửi dữ liệu (như CSS, JavaScript, hình ảnh) đến trình duyệt trước khi trình duyệt yêu cầu. Khác với HTTP/1.1 — nơi client phải gửi từng request riêng lẻ — HTTP/2 cho phép server 'đẩy' tài nguyên dự đoán rằng client sẽ cần, nhằm giảm số lần trao đổi mạng và tăng tốc độ tải trang.

Tính năng này không tồn tại trong HTTP/3: IETF chính thức loại bỏ Server Push khỏi tiêu chuẩn HTTP/3 (RFC 9114) do hiệu quả thấp trong thực tế, khó kiểm soát và gây xung đột với bộ nhớ đệm (cache), đặc biệt khi client đã có tài nguyên hoặc không cần chúng.

Tại sao quan trọng trong SEO?

Tốc độ tải trang là yếu tố xếp hạng trực tiếp của Google từ năm 2018 (cho mobile) và được củng cố qua Core Web Vitals. Server Push giúp cải thiện các chỉ số như First Contentful Paint (FCP)Largest Contentful Paint (LCP) — hai trong ba chỉ số chính của Core Web Vitals — bằng cách giảm độ trễ chờ request/response cho tài nguyên thiết yếu.

Tuy nhiên, lợi ích SEO chỉ xuất hiện nếu Server Push được triển khai chính xác: đẩy đúng tài nguyên, đúng thời điểm và không gây lãng phí băng thông. Ngược lại, đẩy sai có thể làm chậm trang, tăng thời gian tải tổng thể và làm giảm điểm Lighthouse — ảnh hưởng tiêu cực đến thứ hạng.

Cách hoạt động

Khi client gửi request đầu tiên (ví dụ: GET /index.html), máy chủ phân tích nội dung HTML và phát hiện các tài nguyên cần thiết (như /style.css, /app.js). Thay vì đợi client gửi thêm hai request riêng lẻ, server gửi kèm các PUSH_PROMISE frames trong cùng kết nối HTTP/2, rồi truyền luôn dữ liệu của các tài nguyên đó.

Trình duyệt nhận PUSH_PROMISE, kiểm tra xem đã có tài nguyên trong cache chưa. Nếu chưa có, nó chấp nhận và lưu vào bộ nhớ đệm nội bộ; nếu đã có, nó có thể từ chối (RST_STREAM) để tránh trùng lặp.

Hướng dẫn thực hiện

Server Push không được kích hoạt tự động — cần cấu hình thủ công ở mức web server hoặc ứng dụng. Dưới đây là các bước phổ biến:

  1. Xác định tài nguyên thiết yếu: Chỉ đẩy những file nhỏ, dùng ngay trên trang đầu (ví dụ: CSS in-line, font quan trọng, script khởi tạo). Không đẩy hình ảnh lớn, video hoặc tài nguyên chỉ dùng sau tương tác.
  2. Cấu hình trên web server:
    • NGINX: Dùng chỉ thị http2_push trong khối location (từ phiên bản 1.13.9+):
      location = /index.html {
        http2_push /style.css;
        http2_push /app.js;
      }
    • Apache (mod_http2): Dùng H2PushResource trong file cấu hình hoặc .htaccess:
      H2PushResource /style.css
      H2PushResource /app.js
    • Node.js (Express + spdy): Cần dùng thư viện hỗ trợ HTTP/2 và gọi stream.pushStream() trước khi gửi response.
  3. Thử nghiệm và đo lường: Dùng Chrome DevTools → tab Network, lọc theo Protocol: h2, tìm các mục có nhãn push trong cột Initiator. Kiểm tra xem tài nguyên có bị từ chối (RST_STREAM) hay không.
  4. Vô hiệu hóa khi không cần: Nếu dùng CDN (Cloudflare, Cloud CDN), kiểm tra xem tính năng có được bật mặc định không — nhiều CDN đã tắt Server Push vì hiệu quả thấp.

Lỗi thường gặp

  • Đẩy tài nguyên đã có trong cache: Trình duyệt từ chối push → lãng phí băng thông và làm nghẽn luồng. Cách khắc phục: Chỉ đẩy tài nguyên không có thẻ Cache-Control: immutable hoặc không nằm trong cache lâu dài; ưu tiên dùng preload thay thế.
  • Đẩy quá nhiều tài nguyên cùng lúc: Gây tắc nghẽn kết nối, làm chậm tài nguyên quan trọng hơn. Cách khắc phục: Giới hạn tối đa 3–4 push/tạm thời; ưu tiên theo thứ tự render-blocking.
  • Không tương thích với HTTP/2 trên proxy hoặc CDN: Một số proxy (như cũ của AWS ALB) không xử lý PUSH_PROMISE đúng cách → gây lỗi 502 hoặc timeout. Cách khắc phục: Kiểm tra khả năng hỗ trợ HTTP/2 end-to-end; dùng công cụ như http2.pro để kiểm tra.
  • Server Push không hoạt động dù cấu hình đúng: Thường do client đã mở kết nối trước khi server đẩy, hoặc do trình duyệt chặn (Chrome từ phiên bản 79+ giới hạn mạnh việc push tài nguyên ngoài domain gốc). Cách khắc phục: Đảm bảo tài nguyên được đẩy từ cùng origin; kiểm tra header Alt-Svc nếu dùng nâng cấp từ HTTP/1.1.

Ví dụ thực tế

Một trang tin tức sử dụng HTTP/2 với cấu hình NGINX như sau:

server {
  listen 443 ssl http2;
  server_name example.com;

  location = / {
    http2_push /css/main.css;
    http2_push /js/nav.js;
    http2_push /fonts/roboto.woff2;
  }
}

Kết quả đo bằng WebPageTest cho thấy:
– Thời gian FCP giảm từ 1.42s xuống còn 0.98s
– Số request từ 42 xuống còn 38 (do 3 tài nguyên được đẩy thay vì request riêng)
– Tuy nhiên, khi thêm http2_push /images/hero.jpg (file 1.2MB), LCP tăng lên 2.1s do chiếm băng thông — chứng tỏ việc chọn tài nguyên là then chốt.

Câu hỏi thường gặp

Server Push có còn được hỗ trợ trong trình duyệt hiện đại?

Chrome đã vô hiệu hóa Server Push từ phiên bản 79 (tháng 12/2019); Firefox ngừng hỗ trợ từ phiên bản 83 (tháng 11/2020); Safari vẫn giữ nhưng không khuyến khích. Hiện nay, tất cả trình duyệt đều ưu tiên <link rel="preload"> thay thế — vì kiểm soát tốt hơn và tương thích rộng hơn.

Server Push khác gì so với Preload?

Preload là hướng dẫn từ phía client (qua thẻ HTML hoặc header Link: </style.css>; rel=preload), do trình duyệt quyết định thời điểm tải. Server Push là hành động chủ động từ server, không cần thay đổi mã nguồn HTML. Tuy nhiên, Preload linh hoạt hơn, an toàn hơn với cache và được hỗ trợ đầy đủ trên mọi trình duyệt hiện đại.

Có nên dùng Server Push cho website đang chạy HTTP/3?

Không. HTTP/3 không hỗ trợ Server Push — tính năng này đã bị loại bỏ hoàn toàn trong RFC 9114. Nếu bạn nâng cấp lên HTTP/3 (qua QUIC), mọi cấu hình Server Push sẽ bị bỏ qua. Giải pháp thay thế là kết hợp preload, preconnect và tối ưu hóa gói tài nguyên (bundle, code-splitting).

Tính năng Server Push (HTTP/2) Preload (HTML/HTTP) HTTP/3 hỗ trợ?
Chủ thể kích hoạt Máy chủ Client (HTML hoặc header) tùy trường hợp
Hỗ trợ trình duyệt Chrome <79, Firefox <83 Tất cả trình duyệt hiện đại
Tương thích cache Kém (dễ xung đột) Tốt (tuân thủ Cache-Control)
Khả năng đo lường Khó (phụ thuộc vào frame log) Dễ (qua DevTools > Network)