為了提高頁面加載性能拦键,在頁面引入外部js的時(shí)候,可以使用script標(biāo)簽的defer
和async
屬性來使得外部js異步加載
script標(biāo)簽的使用分為三種情況:
- 1.
<script src="demo.js"></script>
沒有defer或async屬性,瀏覽器會(huì)立即加載并執(zhí)行相應(yīng)的腳本。也就是說在渲染script標(biāo)簽之后的文檔之前,不等待后續(xù)加載的文檔元素设联,讀到就開始加載和執(zhí)行善已,此舉會(huì)阻塞后續(xù)文檔的加載;
- 2.
<script async src="demo.js"></script>
有了async屬性离例,表示后續(xù)文檔的加載和渲染與js腳本的加載和執(zhí)行是并行進(jìn)行的换团,即異步執(zhí)行;
- 3.
<script defer src="demo.js"></script>
有了defer屬性宫蛆,加載后續(xù)文檔的過程和js腳本的加載(此時(shí)僅加載不執(zhí)行)是并行進(jìn)行的(異步)艘包,js腳本的執(zhí)行需要等到文檔所有元素解析完成之后,DOMContentLoaded事件觸發(fā)執(zhí)行之前耀盗。
下圖可以直觀的看出三者之間的區(qū)別:
其中藍(lán)色代表js腳本網(wǎng)絡(luò)加載時(shí)間想虎,紅色代表js腳本執(zhí)行時(shí)間,綠色代表html解析袍冷。
從圖中我們可以明確幾點(diǎn):
defer和async在網(wǎng)絡(luò)加載過程是一致的,都是異步執(zhí)行的猫牡;
兩者的區(qū)別在于腳本加載完成之后何時(shí)執(zhí)行胡诗,可以看出defer更符合大多數(shù)場(chǎng)景對(duì)應(yīng)用腳本加載和執(zhí)行的要求;
如果存在多個(gè)有defer屬性的腳本淌友,那么它們是按照加載順序執(zhí)行腳本的煌恢;而對(duì)于async,它的加載和執(zhí)行是緊緊挨著的震庭,無論聲明順序如何瑰抵,只要加載完成就立刻執(zhí)行,它對(duì)于應(yīng)用腳本用處不大器联,因?yàn)樗耆豢紤]依賴二汛。
小結(jié):
defer 和 async 的共同點(diǎn)是都是可以并行加載JS文件,不會(huì)阻塞頁面的加載拨拓,不同點(diǎn)是 defer的加載完成之后肴颊,JS會(huì)等待整個(gè)頁面全部加載完成了再執(zhí)行,而async是加載完成之后渣磷,會(huì)馬上執(zhí)行JS婿着,所以假如對(duì)JS的執(zhí)行有嚴(yán)格順序的話,那么建議用 defer加載醋界。
參考: use_async_or_defer
In general, you should always use async or defer for third party scripts (unless the script does something necessary for the critical rendering path):
Use async if it's important to have the script run earlier in the loading process. This might include some analytics scripts, for example.
Use defer for less critical resources. A video player that's below-the-fold, for example.
Note: If performance is your primary concern, you could wait until your page has reached a key user moment (such as after the critical content has loaded) before adding async scripts. You should also take care not to async load libraries like jQuery just because they are coming from a third-party CDN.
Note: In Blink-based browsers,
async
anddefer
currently lower the priority of the network request for resources so it can cause it to load significantly later than it would as a blocking script. This is useful to know in particular for analytics scripts.
Should you ever load third-party scripts without async or defer? You could make a case for this if the script is a crucial part of your site functionality. For example, if you're loading your main UI library or framework from a CDN, it will be badged as "third-party script" in DevTools, but should be treated as an essential part of your site, not an add-on.
Note that not all scripts work if loaded asynchronously. Check the docs for any third-party scripts you're using. If you're using a script that can't be loaded asynchronously, you might want to consider an alternative, or eliminating the script if possible. Some third parties may highly recommend to load their scripts sync (to get ahead of other scripts), even if they would work fine async so do due diligence when evaluating strategies for loading third-party scripts.