你还记得script标签的async和defer属性吗

1,287 阅读2分钟

script标签用于加载和执行脚本,直接在html中使用该标签,浏览器将按照顺序加载和执行脚本从而阻塞DOM的渲染,尤其是使用第三方脚本时,如果出现服务器响应迟缓或者网络延迟较高,浏览器页面会出现长时间的白屏状态,通过script标签的async和defer属性,可以有效减少这种问题的出现

关键词: DOM渲染 、 js脚本加载 、 js脚本执行 、 异步     


defer

script标签设置了defer属性,浏览器会在不影响DOM渲染的情况下异步加载脚本文件(后台加载),在DOM渲染完成后、DOMContentLoaded事件触发前执行脚本,如果有多个script标签设置了该属性,各个脚本会按引入的顺序执行

尝试

  • 创建一个HTML

31616879-896dbbe0-b253-11e7-9f72-8f259c412a44.png

  • 在浏览器中执行,查看加载和执行情况


31616627-d051b918-b252-11e7-848e-0aa60c24ea61.png

可以看到,脚本2(2.01s)后于脚本1(1.00s)加载完成,但是先执行的是脚本2,定义了defer属性的脚本执行完成后在触发DOMContentLoaded事件


# async


script标签设置了async属性,浏览器会异步在后台加载脚本文件,并在允许的情况下执行脚本,此时的DOM可能还没完成渲染,如果有多个该类型的标签,脚本不一定会按照引入的顺序执行,谁先加载完就马上执行谁,DOMContentLoaded事件先后不定

尝试

  • 创建一个HTML脚本

image.png

  • 浏览器加载和执行情况

31617632-4f5b4b78-b255-11e7-8641-7d03a5e027b2.png

可以看到,,DOMContentLoaded事件先触发,脚本也没有按照引入顺序执行

再次尝试

  • 创建一个渲染时间较长的HTML脚本

31618663-29873404-b258-11e7-8333-b113aa95c0ae.png

  • 查看浏览器执行情况

31619033-314a03dc-b259-11e7-862f-17a0317920bb.png

可以看到,这次DOMContentLoaded事件后触发

可以看到,使用async不会等待dom渲染完成再执行,同时执行顺序也不会按照引入的顺序

甘特图比较

普通脚本

31621391-39849b1a-b25f-11e7-9301-641b1bc07155.png

defer脚本

31621324-046d4a44-b25f-11e7-9d15-fe4d6a5726ae.png

async脚本

31621170-b4cc0ef8-b25e-11e7-9980-99feeb9f5042.png
31622216-6c37db9c-b261-11e7-8bd3-79e5d4ddd4d0.png

使用情景

  • defer

在脚本依赖DOM的情况下使用defer

  • async

脚本不依赖DOM的情况下使用async