defer và async thay đổi khi nào một <script> bên ngoài tải xuống và thực thi so với việc parse HTML. Cả hai đều cho phép script tải xuống song song mà không chặn parser — sự khác biệt là thời điểm thực thi.
html
defer và async thay đổi khi nào một <script> bên ngoài tải xuống và thực thi so với việc parse HTML. Cả hai đều cho phép script tải xuống song song mà không chặn parser — sự khác biệt là thời điểm thực thi.
Thông thường: parse──dừng──[tải+exec]──parse──────── (chậm nhất)
async: parse──────────────────exec──parse──────── (chạy bất cứ khi nào nó tới)
defer: parse───────────────────────────parse──exec (sau khi parse, trước DOMContentLoaded)
async | defer | |
|---|---|---|
| Tải xuống | song song | song song |
| Thực thi | ngay khi tải xong | sau khi HTML parse xong hoàn toàn |
| Giữ thứ tự? | Không (ai xong trước) | Có (thứ tự tài liệu) |
| Chặn parser? | chỉ trong chốc lát khi exec | không bao giờ |
defer — cho các script đụng tới DOM hoặc phụ thuộc lẫn nhau/thứ tự (code app của bạn). Chúng chạy sau khi DOM tồn tại, theo trình tự, ngay trước DOMContentLoaded.async — cho các script bên thứ ba độc lập không phụ thuộc vào DOM hoặc các script khác (analytics, quảng cáo). Thứ tự không quan trọng, chạy chúng ngay khi có thể.<script src="analytics.js" async></script> <!-- độc lập → async -->
<script src="app.js" defer></script> <!-- logic app, có thứ tự → defer -->
Lưu ý: cả hai chỉ áp dụng cho script bên ngoài (src); chúng bị bỏ qua trên script inline. ES module (type="module") được defer mặc định.
Dùng defer/async giữ cho script không chặn việc parse HTML, điều này trực tiếp cải thiện hiệu năng tải và First Contentful Paint.
Chọn đúng cái (defer cho code app có thứ tự, phụ thuộc DOM, async cho các script bên thứ ba fire-and-forget) tránh được cả việc tải chậm lẫn các lỗi phụ thuộc thứ tự.