在 HTML 页面加载优化中,defer 通常是最稳妥的选择,特别适合需要操作 DOM、并且存在执行顺序依赖的外部脚本;async 更适用于完全独立的脚本,例如统计埋点、监测代码这类场景;而把 放到
前,本质上依然会阻塞页面解析,只是把阻塞发生的时机延后了;默认情况下,普通 script 标签会暂停 DOM 构建,直到脚本下载并执行结束。

大多数情况下,给脚本添加 defer 属性,是提升页面加载性能、减少 script 阻塞 DOM 解析最省事也最可靠的做法,但前提必须满足:脚本是通过外部文件引入、确实需要操作 DOM,并且多个脚本之间的执行顺序不能被打乱。如果脚本本身完全独立,比如数据统计、广告追踪、埋点采集等用途,那么使用 async 往往更合适。至于把 移到 前,这种方式只是“表面上更顺畅”,并没有从根本上解决问题——浏览器解析 HTML 时依然会被脚本阻塞,只不过阻塞点被推迟到了页面底部。
浏览器解析 HTML 采用的是流式处理方式,一旦遇到没有添加 通过 JavaScript 动态创建 还有一个非常容易被忽视的点是:即便已经使用了 补充同频道和同主题内容,方便继续浏览更多相关内容。 继续查看同栏目最近更新的文章。 CSS3是现代网页开发的核心技术,涵盖圆角、阴影、渐变、过渡、动画及响应式布局等高频特性。本文梳理了CSS3的核心应用场景、分步学习路径与综合练习案例,帮助初学者快速建立从基础排版到现代交互的完整开发思路,并规避常见样式陷阱。 本文系统讲解CSS标准边框属性border的完整语法结构,涵盖简写与拆分写法、单边控制技巧及border-radius配合方案。针对边框不显示、元素尺寸异常等高频问题提供排查路径,帮助开发者快速掌握边框设置规范并提升界面视觉一致性。 CSS3动画主要分为transition过渡与animation关键帧两类。本文梳理常用属性、简写语法与@keyframes规则,结合悬停、入场、循环等场景给出代码示例与选型建议,帮助开发者快速写出流畅且可控的动画效果。 CSS3渐变色通过纯代码生成平滑颜色过渡,广泛用于按钮、横幅与卡片背景。本文系统梳理线性与径向渐变的核心语法、方向控制、停靠点设置及多层叠加技巧,提供可直接复用的场景代码,并给出兼容性策略与常见渲染异常排查方法,帮助开发者快速构建稳定、可维护的渐变样式。 寻找CSS3手册中文版下载资源时,如何判断来源可靠性、筛选高质量内容并有效使用?本文从获取渠道、版本识别、下载验收到替代方案,提供一套可执行的判断标准,帮助你快速找到适合学习或查阅的中文手册。defer 或 async 的 ,就会立即暂停 DOM 树构建,开始发起脚本请求,并等待脚本下载、解析、执行全部完成后,才继续向下解析页面。即使脚本内容只是简单的一行 console.log,只要它出现在 中,
DOMContentLoaded 时间通常会明显晚于 first-contentful-paintdocument.getElementById(...) is null 放在 中间时,后续 HTML 元素根本不会继续解析,必须等脚本执行结束defer 属性怎么写才真正生效
defer 并不是“写上就一定有效”,它只会对满足两个硬性条件的外部脚本生效:第一,脚本必须带有 src 属性;第二,defer 必须以无值布尔属性的形式出现。只要写法不符合要求,浏览器通常会直接静默忽略,不会报错,也不会给出明显提示,因此仅靠 Network 或 Elements 面板,很多时候很难第一时间发现它实际上没有生效。
(内联脚本上的 defer 会被忽略)(defer 属于布尔属性,不接受值)(当 async 和 defer 同时存在时,defer 会被忽略)build.inlineDynamicImports: true 后,可能会把外部脚本打包成内联代码 → 此时 defer 会彻底失效,因此必须检查最终产出的 HTMLasync 和 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 事件实现 fallback 逻辑const s = document.createElement('script'); s.src = '/app.js'; s.onload = () => init(); document.head.appendChild(s); 默认不会阻塞渲染,如确实需要阻塞,需使用新属性 blocking="render"(当前仅 Chromium 125+ 支持)defer,脚本执行依然会阻塞 DOMContentLoaded 事件的触发;而 async 在执行瞬间同样可能打断 HTML 解析流程。换句话说,它们并不是让 script “完全不阻塞”,而是把阻塞发生的位置和时机做了重新安排。页面到底要不要阻塞、应该在什么阶段阻塞,最终仍然要结合脚本用途、依赖关系以及实际用户体验目标来判断,不能简单地给标签加个属性就认为问题已经彻底解决。相关推荐
同类最新
CSS3入门指南:常用特性解析与实战练习路径
CSS border 边框属性详解:语法、拆分写法与常见问题排查
CSS3动画属性有哪些:常用属性与用法说明
CSS3渐变色语法与常见用法
CSS3手册中文版下载指南:获取渠道、筛选标准与使用建议