async是下载完立即执行、不保序,适合独立脚本;defer是dom解析完按序执行,适合依赖dom或有先后依赖的业务逻辑。

脚本加载用 async 和 defer 的核心区别在于:async 是“下载完立刻执行,不保证顺序”;defer 是“等 DOM 解析完、按书写顺序执行”。选哪个,取决于脚本是否依赖 DOM 或其他脚本。
async:适合完全独立的脚本(如统计、广告)
async 脚本一下载完就立即执行,不等 HTML 解析完成,也不阻塞页面渲染。但多个 async 脚本之间**执行顺序不确定**,不能保证谁先谁后。
- 适用场景:Google Analytics、第三方埋点、无依赖的工具类脚本
- 写法:
<script async src="analytics.js"></script> - 注意:不要在 async 脚本里操作 DOM 元素(可能还没生成),也不要依赖其他脚本已执行
defer:适合依赖 DOM 或需顺序执行的脚本
defer 脚本会和 HTML 并行下载,但**等到整个 HTML 解析完成(DOMContentLoaded 触发前)才按顺序执行**,且一定在 DOM 构建完毕之后。
- 适用场景:Vue/React 初始化、表单验证逻辑、需要操作 DOM 的模块
- 写法:
<script defer src="app.js"></script> - 多个 defer 脚本严格按 HTML 中出现的顺序执行,适合有依赖关系的脚本链
普通 script:默认阻塞解析,慎用
没有 async 或 defer 的 script 会**同步下载并执行**,阻塞 HTML 解析,容易导致白屏或渲染延迟。
- 仅适用于极小、必须同步运行的内联脚本(如 document.write 兼容代码)
- 外部脚本尽量避免不用属性,尤其放在 里时影响更明显
- 如果必须用,可考虑将 script 移到 底部,作为折中方案
组合策略建议
实际项目中常混合使用:
- 首屏无关的第三方 SDK(如客服 widget)用 async
- 主业务逻辑、框架入口用 defer,并确保它们在 HTML 中按依赖顺序排列
- 关键渲染逻辑(如字体加载、主题切换)可结合 defer + DOMContentLoaded 监听做精细控制
- 现代做法:配合 module 类型(
<script type="module"></script>)天然具有 defer 行为,还支持 top-level await 和静态导入分析
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











