Admin vừa sửa dữ liệu, tải lại trang mà một UI block vẫn giữ nội dung cũ. Phản xạ đầu tiên thường là bấm “clear all cache”. Cách đó có thể làm màn hình đổi ngay, nhưng chưa trả lời được câu quan trọng hơn: block đang cũ vì TTL, vì cache key thiếu context, hay vì callback đưa dữ liệu chưa an toàn vào HTML?
Botble hiện có tuỳ chọn cache phần HTML đã render của shortcode. Theo tài liệu Cache Management được kiểm tra ngày 13/10/2026, tuỳ chọn này mặc định tắt và thời gian cache mặc định là 1.800 giây. Cache store lại do CACHE_STORE trong môi trường quyết định. Nghĩa là trước khi bật cho một block động, cần kiểm tra cả độ tươi lẫn ranh giới input/output; chỉ nhìn việc trang tải nhanh hơn là chưa đủ.
Mục lục [Hiển thị]
Botble render shortcode ở đâu?
Shortcode có thể được đăng ký bằng helper add_shortcode() hoặc facade Shortcode::register(). Trong theme, withShortcodes() gắn bước xử lý vào view; ngoài ra có thể gọi do_shortcode() hoặc Blade directive. trang Shortcode chính thức mô tả các đường đi này và cả thuộc tính enable_lazy_loading.
Điểm cần nhớ là callback cuối cùng tạo ra HTML. Nếu HTML đó được cache, lần gọi sau có thể không chạy callback nữa. Điều này rất hợp với block gần như tĩnh, nhưng trở thành rủi ro correctness khi output còn phụ thuộc locale, vai trò người xem, query string hoặc revision dữ liệu.
add_shortcode('inventory-card', 'Inventory card', null,
function ($shortcode) {
$sort = in_array($shortcode->sort, ['featured', 'sale'], true)
? $shortcode->sort
: 'featured';
return Theme::partial('shortcodes.inventory-card', [
'title' => (string) $shortcode->title,
'sort' => $sort,
]);
}
);
Đoạn trên chỉ là khung callback. Việc Blade dùng {{ }} cho text, cho phép giá trị nào đi vào sort, và block có nên cache hay không vẫn phải được quyết định riêng. Đừng nối thẳng attribute vào HTML rồi nghĩ cache sẽ “đóng băng” nó thành an toàn.
Fixture đã kiểm tra những gì?
Môi trường kiểm tra là Windows x64 với Node.js 24.19.0, cache in-memory xác định trước và TTL 1.800 giây. Đây là fixture biên mô phỏng callback, cache hit, validation và output encoding dựa trên tài liệu Botble hiện hành; không phải một bản cài Botble production và cũng không chứng minh core Botble đang tạo cache key theo cách nào.
Bốn request dùng cùng shortcode nhưng thay đổi locale, vai trò và query: vi/guest/featured, en/guest/featured, vi/member/featured và vi/guest/sale. Positive control khi cache tắt chạy callback bốn lần và trả đúng bốn output. Khi cache bật với key cố tình chỉ dựa trên chuỗi shortcode, callback chạy một lần, ba request sau hit cache và chỉ 1/4 output đúng. Khi key gồm shortcode, locale, role, query và revision dữ liệu, cả 4/4 case đều đúng.

Kết quả này cho thấy cách test một ranh giới cache, không phải kết luận rằng Botble có bug. Nếu bản cài thực tế đã phân tách đúng context hoặc cho phép bỏ qua cache với block riêng, matrix sẽ pass. Điều đáng giữ lại là bộ expected output: không có expected thì một cache hit trông rất “xanh” dù trả nhầm nội dung.
Cache key phải phản ánh phần nào của request?
Không nên đưa mọi thứ vào key. Cookie, URL đầy đủ hoặc user ID có thể làm cardinality phình to và biến cache thành bộ nhớ tạm gần như không bao giờ hit. Hãy bắt đầu từ câu hỏi: yếu tố nào thực sự thay đổi HTML?
- Output chỉ phụ thuộc attribute đã chuẩn hoá: key có thể dựa trên tên shortcode và attribute canonical.
- Output thay theo ngôn ngữ: thêm locale, hoặc tách cache theo locale ở layer phù hợp.
- Output thay theo nhóm quyền: cân nhắc role/segment; với dữ liệu riêng tư theo từng tài khoản, tắt cache rendered output thường dễ an toàn hơn.
- Output thay theo query string: chỉ allowlist đúng tham số có ảnh hưởng, không nhét toàn bộ query vào key.
- Output thay khi bản ghi được sửa: thêm revision/version dữ liệu hoặc invalidate đúng key sau sự kiện cập nhật.
Trong fixture, dữ liệu revision 42 được cache. Sau 60 giây, nguồn chuyển sang revision 43 nhưng cùng key vẫn trả 42 vì TTL chưa hết. Gọi invalidation có chủ đích khiến request kế tiếp render 43. Đây là khác biệt giữa “cache hoạt động” và “cache đúng”.
Validation và escape giải quyết hai việc khác nhau
Attribute shortcode là input. Validation trả lời “giá trị này có được phép dùng không?”, còn escaping trả lời “giá trị hợp lệ sẽ được biểu diễn an toàn thế nào trong context đầu ra?”. Một allowlist cho featured/sale không thay thế HTML encoding; e() hoặc Blade escaped echo cũng không biến một giá trị sort tuỳ ý thành business rule hợp lệ.
Fixture dùng chuỗi vô hại <img src=x onerror=alert(1)> làm title. Sau encoding, output không còn thẻ <img> thực thi và chứa marker <img. Giá trị sort ngoài allowlist bị từ chối. AI Assistant Guide của Botble cũng nhắc nguyên tắc sanitize input, escape output và đưa BaseHelper::clean() làm lựa chọn cho HTML cần cho phép có kiểm soát.

Context output rất quan trọng. Text node, HTML attribute, URL và JavaScript không dùng chung một phép escape tuỳ tiện. Với title thuần văn bản, Blade {{ $title }} là mặc định dễ hiểu. Nếu thật sự cho phép một tập HTML, hãy sanitize bằng chính sách rõ ràng trước khi render; không đổi toàn bộ sang {!! !!} chỉ vì muốn giữ một thẻ.
Đừng dùng clear all làm chiến lược invalidation
Tài liệu Botble nói rõ Platform Administration → Cache Management là nơi xoá cache, còn Settings → Cache là nơi cấu hình. Clear all hữu ích để xác nhận nhanh một triệu chứng stale, nhưng nó xoá rộng hơn phạm vi của một block và không sửa thiết kế key. Vài phút sau, vấn đề có thể quay lại.
Ưu tiên ba lựa chọn theo thứ tự:
- Với block tĩnh hoặc thay đổi hiếm, giữ cache và chấp nhận TTL đã công bố.
- Với block phụ thuộc dữ liệu, dùng key có version hoặc quên đúng key/tag khi model thay đổi.
- Với block phụ thuộc session, quyền riêng tư hoặc request có cardinality cao, tắt cache rendered output cho block đó nếu phiên bản/theme hỗ trợ; nếu không, không bật cache shortcode toàn cục cho tới khi có kiểm soát phù hợp.
Nếu vừa deploy mà toàn giao diện cũ, đó là bài toán layer rộng hơn. Checklist Botble hiện giao diện cũ sau deploy tách cache ứng dụng, asset build và quyền file. Còn nếu đổi preset ảnh mà thumbnail không đổi, quy trình tạo lại thumbnail Botble an toàn phù hợp hơn việc flush cache mù quáng.
Lazy loading không tự làm dữ liệu tươi
Botble cho phép thêm enable_lazy_loading="yes" khi generate shortcode. Tài liệu mô tả đây là cơ chế để triển khai tải muộn. Nó thay đổi thời điểm request/render, nhưng không tự xác định cache key và cũng không biết dữ liệu nào vừa đổi.
Nếu endpoint lazy vẫn đọc cùng một entry thiếu locale hoặc role, chỉ là nội dung sai xuất hiện muộn hơn. Nếu shared cache/CDN ở phía trước bỏ qua cookie, vấn đề còn nằm ngoài cache shortcode. Public Cache Control của Botble là tài liệu riêng cho Varnish/CDN; đừng trộn hai layer khi debug.
Bảng quyết định trước khi bật cache
| Loại output | Cache | Key / invalidation | Kiểm tra bắt buộc |
|---|---|---|---|
| Tĩnh theo attribute | Có thể bật | Attribute đã chuẩn hoá + TTL | Hai request giống nhau: callback giảm, HTML giữ nguyên |
| Phụ thuộc dữ liệu có revision | Có điều kiện | Version hoặc invalidate khi update | Update dữ liệu trong TTL phải cho output mới |
| Phụ thuộc locale/query allowlist | Có điều kiện | Thêm đúng context vào key | Matrix ít nhất hai locale và hai query |
| Phụ thuộc session/quyền riêng tư | Thường nên tắt | Không dùng shared rendered cache thiếu partition | Guest/member không được nhìn chéo output |
| Có input không tin cậy | Không liên quan tới an toàn input | Validate rồi escape theo context | Chuỗi HTML vô hại không trở thành DOM thực thi |
Trước khi bật trên site thật, ghi lại cache driver, TTL, shortcode nào được phép cache và expected output theo context. Sau đó chạy positive control, negative control và một lần cập nhật dữ liệu. Với nội dung có thể crawl, kiểm tra thêm HTML public theo checklist SEO kỹ thuật cho blog Botble; block lazy hoặc stale không chỉ là chuyện nhìn thấy trên màn hình.
Chốt lại
Cache shortcode đáng bật khi output ổn định và ta chứng minh được key cùng invalidation phản ánh đúng dữ liệu. Với block động, hãy kiểm tra bốn thứ riêng biệt: context tạo HTML, validation, escaping và vòng đời cache. Clear all chỉ là phép chẩn đoán; lazy loading chỉ đổi thời điểm tải. Một matrix nhỏ có expected output thường nói thật hơn cảm giác “refresh thấy ổn rồi”.