defer和async是script標簽的兩個屬性,用于在不阻塞頁面文檔解析的前提下,控制腳本的下載和執(zhí)行摔寨。
先了解瀏覽器的加載和渲染過程:
- 瀏覽器先通過HTTP協(xié)議請求服務器,服務器響應瀏覽器獲取HMTL文檔并開始從上到下解析久免,構建DOM樹;
- 在構建DOM樹過程中扭弧,如果遇到外聯(lián)的樣式或腳本聲明阎姥,會暫停HTML文檔解析,創(chuàng)建新的網(wǎng)絡連接鸽捻,并開始下載樣式文件和腳本文件丁寄;
- 樣式文件下載完成后氨淌,構建CSSDOM;腳本文件下載完成后伊磺,解釋并執(zhí)行,然后繼續(xù)解析文檔構建DOM樹删咱。
-
完成文檔解析后屑埋,將DOM和CSSDOM進行關聯(lián)和映射,最后將視圖渲染到瀏覽器窗口痰滋。
在這個過程中摘能,腳本文件的下載會阻塞文檔的解析,有時候會影響用戶體驗敲街,所以就使用defer和async進行控制团搞。
Paste_Image.png
1.當<script>沒有任何屬性。HTML文件在解析過程中遇到<script>標簽多艇,HTML的解析將停止逻恐,并將請求獲取外部的js文件,并執(zhí)行該腳本文件,執(zhí)行完之后才繼續(xù)解析html峻黍。
2.如果加了async <script async>,瀏覽器在HTML解析過程中下載js文件复隆,js加載完之后暫停HTML解析器,并執(zhí)行js,js執(zhí)行完之后再繼續(xù)解析HTML姆涩。也就是說加載和渲染后續(xù)文檔的過程挽拂,與js文件的加載并行。
3.<script defer>
defer在HTML解析過程中下載js文件骨饿,只有解析完HTML后才執(zhí)行該js文件亏栈。有defer的腳本可以按照它們在文檔中出現(xiàn)的順序執(zhí)行。defer使加載后續(xù)文檔元素的過程將和 js 的加載并行進行(異步)宏赘,但js的執(zhí)行要在所有元素解析完成之后绒北。
有什么區(qū)別?
defer:
如果有多個聲明了defer的腳本,則會按順序下載和執(zhí)行置鼻。
defer腳本會在DOMContentLoaded和load事件之前執(zhí)行镇饮。
async:
如果有多個聲明了async的腳本,其下載和執(zhí)行也是異步的箕母,不能確保彼此的先后順序 .
async會在load事件之前執(zhí)行储藐,但并不能確保與DOMContentLoaded的執(zhí)行先后順序.
什么時候應該用什么?
如果腳本是模塊化的嘶是,并且不依賴任何腳本钙勃,則使用async 。
如果腳本依賴或被另一個腳本依賴聂喇,那么使用defer 辖源。
如果腳本很小并且被async腳本所依賴蔚携,那么使用在async腳本后面的內(nèi)聯(lián)腳本。