在多数场景下,为外部脚本添加 defer 通常是更省心、也更稳妥的做法,但前提是要同时满足几个条件:脚本通过外部文件引入、确实需要操作 DOM,并且执行顺序不能被打乱。如果脚本本身完全独立,例如统计埋点、广告跟踪这类功能,那么使用 async 往往更合适。至于把 放到 前,这种方式只是把阻塞延后到页
页面加载时script标签如何避免阻塞DOM解析
时间:2026-08-18
浏览:595
文章目录
在多数场景下,为外部脚本添加 defer 通常是更省心、也更稳妥的做法,但前提是要同时满足几个条件:脚本通过外部文件引入、确实需要操作 DOM,并且执行顺序不能被打乱。如果脚本本身完全独立,例如统计埋点、广告跟踪这类功能,那么使用 async 往往更合适。至于把 放到 前,这种方式只是把阻塞延后到页面底部,并没有真正避免解析阻塞。

默认 script 为什么会阻塞 DOM 解析
浏览器会以流式方式解析 HTML。当遇到没有 通过 JavaScript 动态创建 容易被忽略的一点是:即使使用了 defer 或 async 的 时,会立即暂停 DOM 构建,发起脚本请求,并在下载、解析、执行全部完成后,才继续后续 HTML 的解析。即使脚本内容只有一行 console.log,只要它位于 中, 里的文本、按钮和图片都需要等待它执行完成。
DOMContentLoaded 时间明显晚于 first-contentful-paintdocument.getElementById(...) is null 放在 中间时,后续 HTML 元素不会继续解析,必须等脚本执行结束defer 属性如何写才能生效
defer 并不是加上就一定有效,它只对满足条件的外部脚本生效:一是必须带有 src 属性,二是 defer 需要以无值布尔属性形式出现。只要写法不符合要求,浏览器通常不会报错,也不会提示失效,因此很容易被忽略。
(内联脚本上的 defer 会被忽略)(defer 是布尔属性,不识别赋值形式)(async 与 defer 同时存在时,defer 会被忽略)build.inlineDynamicImports: true 后,可能把外部脚本转成内联形式,导致 defer 完全失效,因此需要检查最终生成的 HTMLasync 和 defer 的执行时机区别
async 和 defer 的核心区别在于执行时机。带有 async 的脚本一旦下载完成,就会立即执行,不会等待 DOM 是否构建完成;而带有 defer 的脚本会在 DOM 树构建完成后执行,并且执行时机位于 DOMContentLoaded 事件触发之前。这个差异会直接影响诸如 document.getElementById、getElementsByClassName 等 DOM 操作是否能够安全运行。
async 适用于:Google Analytics、百度统计、广告 SDK 等完全独立、不操作 DOM、也不依赖其他脚本的代码defer 适用于:主业务逻辑、UI 组件初始化、需要读取 data- 属性或绑定事件的脚本async 脚本的执行顺序不固定,而多个 defer 脚本会严格按照 HTML 中的书写顺序执行type="module" 脚本默认具有类似 defer 的行为,因此再额外添加 defer 不会产生作用document.write() 出现在 defer 或 async 脚本中时,会清空整个文档,因此必须移除动态创建 script 标签的特点
标签,并插入到 document.head 或 document.body 中,可以更灵活地控制加载时机,也便于实现错误重试和避免重复加载。不过,这种方式会绕过预加载扫描器(preload scanner),浏览器无法提前发现并并发请求这些资源。
window.myLib 是否存在,再决定是否继续加载;也可以监听 load 和 error 事件实现 fallbackconst s = document.createElement('script'); s.src = '/app.js'; s.onload = () => init(); document.head.appendChild(s); 默认不会阻塞渲染;如果需要阻塞渲染,需要使用新属性 blocking="render",目前仅 Chromium 125+ 支持script 避免阻塞时需要注意的关键点
defer,脚本执行仍然会阻塞 DOMContentLoaded 事件的触发;而 async 在执行时依旧会中断 HTML 解析。也就是说,它们并不是完全不阻塞,而是把阻塞发生的时机和位置做了调整。是否需要阻塞、在哪个阶段阻塞,仍然要根据脚本用途和页面体验目标来决定。
实用工具推荐
绿化、压缩、噪点和虚拟水印,自由调节做旧程度。
选择画质和输出格式,预览压缩前后的大小。