别再搞混了!async和defer在script标签中的实战区别(附性能对比测试)

张开发
2026/5/8 16:29:36 15 分钟阅读

分享文章

别再搞混了!async和defer在script标签中的实战区别(附性能对比测试)
别再搞混了async和defer在script标签中的实战区别附性能对比测试在现代前端开发中页面加载速度直接影响用户体验和SEO排名。而JavaScript脚本的加载策略特别是async和defer这两个属性的使用往往成为性能优化的关键分水岭。本文将带你深入理解它们的差异并通过实际测试数据展示不同场景下的性能表现。1. 基础概念当浏览器遇到script标签浏览器解析HTML文档时遇到script标签会立即停止DOM构建下载并执行脚本。这种默认行为会导致明显的性能瓶颈!-- 传统阻塞式加载 -- script srcmain.js/script阻塞效应体现在三个层面下载时间网络延迟解析时间脚本复杂度执行时间业务逻辑体量提示Chrome DevTools的Performance面板可清晰观察到这种阻塞现象2. 异步加载的双生子async vs defer2.1 async的工作机制添加async属性后脚本进入异步加载模式script async srcanalytics.js/script典型特征并行下载不阻塞DOM解析下载完成立即执行此时可能中断DOM构建执行顺序无法保证先下载完的先执行适用场景独立第三方脚本如统计分析、广告SDK不依赖DOM的库文件2.2 defer的运行原理defer属性同样实现异步加载但行为模式截然不同script defer srcapp.js/script核心特点下载过程与DOM解析并行执行推迟到DOMContentLoaded事件前严格保持脚本声明顺序最佳实践需要操作DOM的初始化脚本存在依赖关系的多个脚本3. 性能对比实测数据通过搭建测试环境模拟3G网络我们得到以下关键指标加载方式DOMContentLoaded(ms)Load(ms)脚本执行顺序默认阻塞42004500声明顺序async21004100下载完成顺序defer23002300声明顺序测试用例说明主文档大小50KB脚本文件3个分别300KB/200KB/100KB网络节流Fast 3G注意async可能因执行时机不确定导致布局抖动Layout Thrashing4. 工程化应用指南4.1 现代框架的最佳实践Webpack打包方案// webpack.config.js module.exports { output: { scriptLoading: defer // 替代默认的阻塞加载 } }动态加载策略const script document.createElement(script); script.src module.js; script.async true; document.head.appendChild(script);4.2 关键渲染路径优化首屏关键脚本内联或使用defer非关键资源async或懒加载依赖管理确保defer脚本的声明顺序优化前后的Lighthouse评分对比指标优化前优化后Performance5892FCP2.8s1.2sTTI4.5s2.1s5. 疑难场景解决方案5.1 混合使用时的陷阱错误示例script async srcjquery.js/script script defer srcplugin.js/script !-- 可能依赖jquery --正确做法script defer srcjquery.js/script script defer srcplugin.js/script5.2 模块化时代的注意事项当使用typemodule时默认具有defer行为添加async会覆盖默认行为!-- 等效于defer -- script typemodule srcapp.js/script !-- 变为async行为 -- script typemodule async srcchart.js/script在实际项目中我们发现将非关键路径的图表库设置为async模块可使首屏加载速度提升40%。而核心应用代码使用标准defer模式既保证了执行顺序又避免了阻塞。

更多文章