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
-
Yellorn: cái tab tôi muốn có mỗi khi JSON bẩn và webhook bắt đầu giở trò
Một bài viết tự nhiên về Yellorn: sửa JSON, XML, YAML, CSV bị lỗi, publish mock webhook API, gửi HTTP request và gom workflow debug integration vào một browser workspace.
-
Set Up Google OAuth Production Bằng Đúng 1 Prompt: Khi Tôi Để Cursor Tự Bấm Qua Google Cloud Console
Tôi nhờ một AI agent dựng Google OAuth chuẩn production cho yellorn.com. Đúng một prompt sau, nó đã tự bấm qua Google Cloud Console, dựng consent screen, tạo OAuth client, đẩy secret lên Cloudflare và deploy lên prod. Tôi chỉ ngồi nhâm nhi cà phê.
-
MoneyPrinterV2: 18.000 Sao GitHub Và Cái Máy In Nội Dung Tự Động
Ollama viết kịch bản, KittenTTS đọc, Gemini vẽ hình, MoviePy ghép video. Bạn ngồi uống cà phê. YouTube Short tự lên kênh.
-
Project N.O.M.A.D.: Xây lô cốt tri thức cho ngày không có mạng
Khi đám mây bay đi mất, thứ còn lại trong ổ cứng mới là cứu cánh.