优先用 defer 处理依赖 dom 或其他脚本的外链脚本,确保 dom 就绪且按序执行;完全独立的上报类脚本用 async;禁用同步加载,避免阻塞解析。

选 defer 还是 async,不是看“谁更先进”,而是看脚本是否依赖 DOM 或其他脚本——依赖就用 defer,完全独立就用 async;默认不加属性的同步加载必须避免。
脚本要操作 DOM 或绑定事件?必须用 defer
常见错误现象:document.getElementById("app") 返回 null,addEventListener 报错,或 Vue/React 初始化失败。这是因为脚本在 DOM 尚未解析完时就执行了。
-
defer保证脚本执行时整个 DOM 已构建完毕,document.body、document.head全部可用 - 多个
defer脚本严格按 HTML 中出现顺序执行,适合「库 + 业务」组合,例如:<script src="vue.js" defer></script><script src="app.js" defer></script> -
defer只对带src的外部脚本生效;写成<script defer>init();</script>会被浏览器忽略,内联脚本不会延迟 - Webpack/Vite 构建产物若已使用
type="module",再手动加defer实际无效(模块脚本默认具defer语义)
脚本只上报数据、不读 DOM、也不被其他脚本调用?优先 async
典型表现:脚本里只有 navigator.sendBeacon、fetch 上报,没任何 document. 调用,也不依赖 lodash 或 jQuery 等前置库。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
-
async下载完立刻执行,可能发生在 HTML 解析中途,所以不能假设 DOM 存在 - 多个
async脚本执行顺序不确定——analytics.js和ads.js谁先下完谁先跑,互不影响 - 别把主业务脚本(如
main.js)设为async:体积大 + 执行慢 = 中断解析拖慢首屏 -
async和defer不能共存,浏览器会按规范只认async行为
不加属性的 <script src=""></script> 是性能雷区
它会让浏览器暂停 HTML 解析,等脚本下载 + 执行完才继续——网络慢时白屏明显,首屏时间直接拉长。
- 除非是极小的内联 polyfill(如检测
Promise是否存在),否则所有外部脚本都应明确指定defer或async - 放在
里的同步脚本危害最大,尤其 SSR 场景下容易让首屏渲染卡住 - 动态创建 script 标签(
document.createElement('script'))是更可控的替代方案,适合按需加载或兼容 IE10 以下
容易被忽略的边界情况
defer 只管外链脚本的执行时机,不管它内部的动态行为。
- 即使加了
defer,如果脚本里用了import(),后续模块的加载和执行仍不受约束,得靠代码自己兜底 -
document.write在defer/async脚本中直接报错,必须禁用 - 监听加载完成要用
script.onload,不是DOMContentLoaded——后者是整个 HTML 解析完的信号,和单个脚本无关 - IE8+ 才正确支持
defer;IE10 及以下不支持async,老项目需评估兼容性
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










