Appearance
脚本加载:parser-blocking、defer、async 与模块脚本
主题边界
- 脚本加载涉及 HTML 解析器、预加载扫描器、网络下载和 JS 执行时机。
- 只说 defer 与 async 的顺序差异不够,还要理解它们为什么影响首屏与事件时序。
机制与流程
- 普通脚本默认 parser-blocking:HTML 解析遇到
<script>会暂停,等待脚本下载并执行,再继续解析。 defer脚本可并行下载,但会等到文档解析完成后按出现顺序执行,且通常在DOMContentLoaded之前完成。async脚本并行下载,谁先完成谁先执行,不保证相对顺序;模块脚本默认类似 defer,但依赖图解析和 top-level await 会改变完成时机。
关键差异
defer适合有顺序依赖的初始化脚本;async适合互不依赖的统计、广告等旁路脚本。type="module"除了加载时机不同,还引入模块作用域、CORS 获取与依赖图。
边界条件
- 把所有脚本都加
async容易打乱初始化顺序,导致运行时竞态。 - 模块脚本默认严格模式,且跨域获取时遵守更严格的 CORS 规则。
工程落点
- 脚本标签位置、资源提示、代码分割和 hydration 启动时机都会受加载模型影响。
- 排查首屏白屏和埋点时序问题时,要先确认脚本是否阻塞了解析或抢占了主线程。