第三方脚本该用async还是defer取决于是否依赖DOM及执行顺序要求:埋点类(如analytics.js)无DOM依赖,用async;UI组件类(如地图API)需操作DOM且有调用依赖,必须用defer;内联脚本加二者无效,多个async执行顺序不确定,defer严格按HTML顺序执行。

第三方脚本是页面白屏和 LCP 恶化的主因,不是加个 async 就完事——得按依赖关系选执行时机、用 preconnect 降连接延迟、动态加载兜底风险。
怎么判断一个第三方脚本该用 async 还是 defer
关键看它是否读取或操作 DOM,以及是否需要和其他脚本保持顺序:
- 埋点、错误监控类(如
analytics.js、sentry.min.js)——无 DOM 依赖、不干扰业务逻辑,用async;下载完立刻执行,越早采集数据越好 - UI 组件 SDK、初始化框架(如某些地图 API、表单校验库)——必须等
document可用,且多个脚本之间有调用依赖,必须用defer - 内联脚本(
<script>console.log(...)</script>)加async或defer会被忽略,别白费劲 - 多个
async脚本执行顺序不确定,defer严格按 HTML 中出现顺序执行——这是线上偶发错乱的根源之一
preconnect 和 preload 写在哪、写多少才有效
preconnect 不下载资源,只提前做 DNS 查询 + TCP 握手 + TLS 协商;preload 才真正发起资源请求。两者配合才有意义:
-
preconnect必须放在最顶部,且只对「真会用到」的第三方域名开,比如https://www.googletagmanager.com,而不是泛写https://cdn.jsdelivr.net -
preload的as属性必须准确:as="script"才能让预加载的 JS 被后续<script src="..."></script>复用;写成as="fetch"或漏掉,优先级直接掉到low,等于没写 - 字体必须加
crossorigin:<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>,否则浏览器拒绝应用 - 别对
main.js这类已用defer的入口文件再preload——冗余调度,反而挤占首屏 CSS 带宽
动态加载第三方脚本时怎么避免执行失败或污染全局
当脚本加载时机由用户行为触发(比如点击弹窗才加载聊天组件),静态标签就不够用了:
立即学习“前端免费学习笔记(深入)”;
- 用
document.createElement('script')创建后,显式设置crossorigin="anonymous",否则脚本报错无法捕获堆栈 - 加载完成前不要访问
window.SomeSDK,加onload回调或 Promise 包装,避免undefined is not a function - 通过
iframe或Web Worker隔离高风险 SDK(如广告、外链统计),防止其执行document.write或无限循环拖垮主线程 - 所有动态加载的脚本,建议加上超时控制(如 8s 后 reject),避免长期 pending 卡住后续逻辑
真正难的不是知道该用哪个属性,而是搞清每个第三方脚本在你页面里实际干了什么:它读 DOM 吗?改 document.cookie 吗?监听 scroll 吗?这些行为决定了你能不能放心让它 async,或者必须塞进 defer 队列里排队。漏掉任意一项,性能优化就可能变成稳定性隐患。



















