Tại Sao Production Vẫn Chạy Code Cũ Thế?
Vừa deploy code mới nhưng web vẫn hiện cái nút cũ rích từ tuần trước? Hãy cùng ngồi xuống nói chuyện về trí nhớ 'qua dai' của trình duyệt và cách xử lý nó.

Đã bao giờ bạn mất cả 30 phút cuộc đời chỉ để F5 trình duyệt, xóa cache, bật tab ẩn danh (incognito), thậm chí đổi cả wifi chỉ vì cái nút bạn vừa đổi màu trên local nó không chịu hiện trên production chưa?
Ở máy mình (Localhost)? Mượt. Lên mạng (Production)? Vẫn là cái web từ tuần trước.
Nếu bạn đang deploy lên Firebase, Vercel, hay Netlify và từng hét vào màn hình “NHƯNG MÁY TAO CHẠY NGON MÀ!”, bài viết này là dành cho bạn.
Câu Chuyện Về Người Pha Chế “Hay Quên”
Hãy tưởng tượng một quán cà phê quen thuộc. Sáng nào bạn cũng ghé và gọi đúng một món: “Cho ly như cũ nha em!” (một ly bạc xỉu đá).
Bạn pha chế (Barista) đã quá quen mặt bạn. Vừa thấy bóng bạn từ xa, bạn ấy đã múc sẵn một ly để lên mặt quầy vì biết thừa bạn sẽ gọi món đó. Nhanh gọn, lẹ làng.
Nhưng hôm nay đẹp trời, bạn muốn đổi gió. Bạn muốn uống “Như cũ… nhưng ít sữa thôi”.
Bạn bước vào, hô to “Như cũ nha em!”, và bùm - bạn nhận được ngay ly bạc xỉu y chang hôm qua (nhiều sữa).
“Ủa không,” bạn nói, “Nay anh đổi món mà!” “Dạ xin lỗi anh,” bạn pha chế đáp, “Tại lệnh ghi là ‘Như cũ’, nên em đưa cái ly em làm sẵn cho lẹ.”
Đó chính là Caching.
Nhưng khoan, thực ra có tới hai tầng “người” đang ngăn cản bạn nhận ly nước mới:
- Trí não của bạn (Browser): Bạn nhớ ra mình còn ly cà phê uống dở hôm qua để trên bàn. Tiện tay cầm lên uống luôn cho lẹ khỏi đi mua.
- Quản lý cửa hàng (CDN): Kể cả khi bạn lết xác ra quán, ông Quản lý (Cloudflare/Firebase) đã đứng ngay cửa với một khay “Bạc xỉu” pha sẵn từ sáng sớm để phát cho khách. Ổng chặn bạn lại, đưa nước, rồi đẩy bạn ra về. Bạn còn chưa kịp gặp người pha chế (Server) gốc luôn cơ.
- Bạn = Trình duyệt (Browser)
- Quản lý = CDN (Cloudflare/Firebase)
- Người pha chế = Máy chủ gốc (Origin Server)
- “Ly như cũ” = File
main.jshoặcstyle.css
Khi trang web yêu cầu file main.js, ông CDN sẽ lục kho và bảo: “À, tôi có 1000 bản copy của main.js từ hôm qua nè. Xài đỡ đi!”
Yêu cầu của bạn còn chưa chạm tới được máy chủ. CDN đã chặn đầu rồi. Nó không quan tâm nội dung file có gì thay đổi đâu, nó chỉ nhìn tên file thôi.
Giải Pháp: Đổi Tên Món Gọi
Làm sao để chắc chắn bạn nhận được ly nước mới? Đừng gọi “Ly như cũ”. Hãy gọi “Đơn hàng #90210”.
Ngày mai muốn uống món khác? Gọi “Đơn hàng #90211”.
Lúc này, bạn pha chế không thể đưa ly cũ cho bạn được, vì mã số trên ly cũ không khớp với mã bạn vừa đọc. Họ bắt buộc phải làm ly mới.
Trong lập trình web, cái này gọi là Asset Fingerprinting (hoặc Cache Busting).
Thay vì bảo trình duyệt tải main.js, ta bảo nó tải main.abc12345.js.
Khi ta sửa code, ta đổi luôn tên file: main.xyz98765.js.
Trình duyệt thấy cái tên lạ hoắc chưa gặp bao giờ -> Bắt buộc phải tải mới.
Sửa Lỗi Này Trong Hugo
Nếu bạn dùng Hugo, bạn không cần đổi tên file bằng tay (may phước). Hugo có hàm resources.Fingerprint để làm việc đó tự động.
Trước đây code footer của tôi trông như này:
{{- $script := resources.Get "ts/main.ts" | js.Build $opts -}}
<script src="{{ $script.RelPermalink }}"></script>
Nó tạo ra file tên là main.js. Chán ngắt. Dễ bị cache. Nguy hiểm.
Tôi đổi nó thành:
{{- $script := resources.Get "ts/main.ts" | js.Build $opts | resources.Fingerprint "sha256" -}}
<script src="{{ $script.RelPermalink }}" integrity="{{ $script.Data.Integrity }}"></script>
Giờ thì Hugo sẽ tạo ra file dạng:
/ts/main.50550e6c64a7ed...2afc66aa.js
Mỗi khi tôi sửa dù chỉ một dấu chấm trong main.ts, chuỗi mã kia sẽ thay đổi.
Mã mới = Tên file mới = Code mới cứng.
Bài Học Rút Ra
Browser caching là bạn thân của tốc độ, nhưng là kẻ thù của sự cập nhật (updates).
Đừng tin vào “Hard Refresh” (Ctrl+F5). Nó có thể sửa lỗi cho bạn, nhưng người dùng của bạn đâu có biết phím tắt đó. Họ sẽ chỉ thấy một trang web lỗi và vỡ layout.
Luôn luôn fingerprint (lấy dấu) các file tài nguyên (js/css) của bạn. Bắt người pha chế phải làm ly mới cho bạn mỗi ngày. ☕
Bài viết liên quan
Tencent BrowserSkill Là Gì: Cho AI Dùng Chung Trình Duyệt Không Cướp Chuột
Tencent BrowserSkill kết nối AI agent với Chrome mà không cướp chuột hay bắt đăng nhập lại. Cơ chế mượn tab thông minh, vượt captcha và giữ nguyên bảo mật.
Nuôi Tôm AI 0 Đồng: Biến Laptop Vỡ Màn Thành Server Kỹ Sư Tự Trị 24/7
Biến laptop LG Gram vỡ màn thành server homelab tự trị 24/7 với 0 đồng: pin chống sập, Bubblewrap xoay tua quota Google, cày code cho thằng chủ rảnh tay đi cà phê.
Claude Blog Giải Thích: Cỗ Máy Viết Bài Tự Động 5 Vòng Kiểm Duyệt
Mổ xẻ AgriciDaniel/claude-blog: kiến trúc 32 sub-skills, 5 subagent, và bộ Delivery Contract 5 cửa chặn đứng bài viết rác từ LLM trước khi tới tay người dùng.
SEO Machine Giải Thích: Cỗ Máy Nội Dung Tăng Trưởng B2B SaaS
Mổ xẻ TheCraigHewitt/seomachine: cách workspace Claude Code kết hợp dữ liệu GSC, DataForSEO và 10 context file để biến bài blog kỹ thuật thành doanh thu MRR.