Defer Attribute
Thuộc tính script HTML làm chậm việc thực thi script cho đến khi DOM được phân tích xong, không chặn render nhưng vẫn tải đồng bộ.
Defer Attribute là gì?
Defer attribute là một thuộc tính HTML được thêm vào thẻ <script> để yêu cầu trình duyệt tải file JavaScript đồng bộ (cùng lúc với việc phân tích HTML), nhưng hoãn thực thi cho đến khi toàn bộ cây DOM đã được xây dựng xong — tức là sau khi kết thúc quá trình parsing, trước khi sự kiện DOMContentLoaded được kích hoạt.
Khác với async, defer giữ nguyên thứ tự thực thi các script theo thứ tự xuất hiện trong HTML. Đây là yếu tố quan trọng khi script phụ thuộc lẫn nhau (ví dụ: thư viện trước, rồi mới đến mã tùy chỉnh).
Tại sao quan trọng trong SEO?
Defer ảnh hưởng trực tiếp đến tốc độ hiển thị nội dung (First Contentful Paint – FCP) và thời gian tương tác đầu tiên (First Input Delay – FID) — hai chỉ số cốt lõi trong Core Web Vitals. Khi script chặn render bị loại bỏ, trình duyệt có thể vẽ giao diện nhanh hơn, giúp người dùng thấy nội dung sớm hơn — điều Google đánh giá cao trong xếp hạng tìm kiếm.
Cụ thể:
- Giảm thời gian chặn parsing HTML → tăng tốc độ xây dựng DOM → cải thiện FCP
- Tránh tình trạng “trắng màn hình” hoặc “chậm phản hồi” trên thiết bị di động
- Hỗ trợ tốt hơn cho các trang có nhiều script bên thứ ba (analytics, chat, quảng cáo) mà không làm chậm trải nghiệm người dùng
- Không ảnh hưởng đến khả năng thu thập dữ liệu của bot Googlebot (vì Googlebot hỗ trợ
defertừ phiên bản Chrome 41 trở đi)
Cách hoạt động
Khi gặp thẻ <script defer src="file.js"></script>, trình duyệt:
- Tải file
file.jsđồng bộ cùng lúc với việc phân tích HTML (không chặn parsing) - Giữ lại việc thực thi script cho đến khi cây DOM hoàn tất (sau khi
</html>được xử lý) - Thực thi các script có
defertheo đúng thứ tự khai báo, ngay trước khi phát sinh sự kiệnDOMContentLoaded
Lưu ý: defer chỉ áp dụng cho script ngoài (có thuộc tính src). Script nội tuyến (<script>...</script>) không hỗ trợ defer.
Hướng dẫn thực hiện
Để áp dụng defer hiệu quả, làm theo các bước sau:
- Xác định script nào có thể hoãn: ưu tiên các script không cần chạy ngay khi tải (ví dụ: thống kê, chia sẻ mạng xã hội, lazy-loading ảnh, script xử lý UI sau khi DOM sẵn sàng)
- Loại bỏ script chặn render không cần thiết: kiểm tra bằng công cụ Lighthouse hoặc PageSpeed Insights — nếu báo “Eliminate render-blocking resources”, đó là ứng cử viên hàng đầu
- Thêm thuộc tính
defervào thẻ<script>:<script src="analytics.js" defer></script> <script src="menu.js" defer></script>
- Đảm bảo thứ tự đúng: nếu
menu.jsphụ thuộc vàoutils.js, đặtutils.jstrước trong HTML - Không kết hợp
defervớiasync: trình duyệt sẽ bỏ quadefernếu cả hai cùng tồn tại - Test kỹ sau khi triển khai: kiểm tra console, đảm bảo không có lỗi “undefined function” do script chưa chạy kịp
Lỗi thường gặp
Dưới đây là những sai lầm phổ biến và cách khắc phục:
| Lỗi | Dấu hiệu | Cách khắc phục |
|---|---|---|
Dùng defer cho script nội tuyến |
Thuộc tính bị bỏ qua, script vẫn chạy ngay khi gặp | Chuyển sang script ngoài (tạo file .js riêng) hoặc dùng document.addEventListener('DOMContentLoaded', ...) |
| Thiếu thứ tự phụ thuộc | Lỗi ReferenceError hoặc chức năng giao diện không hoạt động |
Sắp xếp lại thứ tự thẻ <script defer> trong HTML theo logic phụ thuộc |
Kết hợp defer và async |
Chỉ async được áp dụng, defer bị bỏ qua |
Loại bỏ một trong hai — chọn defer nếu cần thứ tự, async nếu độc lập và ưu tiên tốc độ tải |
Dùng defer cho script cần chạy ngay (ví dụ: critical JS) |
Giao diện bị lỗi hoặc thiếu hành vi cần thiết trước khi người dùng tương tác | Giữ script đó ở dạng nội tuyến + type="module" hoặc inline nhỏ, hoặc dùng type="module" (tự động hoãn như defer) |
Ví dụ thực tế
Một trang tin tức có cấu trúc script như sau:
<!-- Trước khi tối ưu --> <script src="jquery.min.js"></script> <script src="share-buttons.js"></script> <script src="ads.js"></script>
Sau khi áp dụng defer:
<!-- Sau tối ưu --> <script src="jquery.min.js" defer></script> <script src="share-buttons.js" defer></script> <script src="ads.js" defer></script>
Kết quả đo được qua Lighthouse (trên thiết bị di động, mạng 3G giả lập):
- FCP giảm từ 3.8s → 1.9s
- FID giảm từ 120ms → 15ms
- Core Web Vitals: từ “Cần cải thiện” → “Tốt”
Lưu ý: Kết quả cụ thể tùy trường hợp — phụ thuộc vào kích thước script, số lượng tài nguyên, và cấu hình máy chủ.
Câu hỏi thường gặp
Defer có làm chậm tải script không?
Không. Việc tải script vẫn diễn ra song song với parsing HTML — chỉ việc thực thi mới bị hoãn. Thời gian tải (download) không thay đổi.
Defer có tương thích với mọi trình duyệt?
Có. Hỗ trợ đầy đủ từ Internet Explorer 10+, Chrome 1+, Firefox 4+, Safari 5.1+, Edge 12+. Không cần polyfill.
Có nên dùng defer cho mọi script?
Không. Chỉ dùng cho script không cần chạy ngay khi tải. Script xử lý layout ban đầu, khởi tạo framework (React/Vue nếu dùng SSR), hoặc script liên quan đến hiển thị nội dung chính nên được tối ưu khác (inline nhỏ, module, hoặc preload). Việc áp dụng đại trà có thể gây lỗi chức năng.