defer和async是script標(biāo)簽的兩個(gè)屬性,用于在不阻塞頁(yè)面文檔解析的前提下,控制腳本的下載和執(zhí)行。
在介紹他們之前,先了解一下頁(yè)面的加載和渲染過(guò)程:
- 瀏覽器通過(guò)HTTP協(xié)議請(qǐng)求服務(wù)器,獲取HMTL文檔并開始從上到下解析,構(gòu)建DOM;
- 在構(gòu)建DOM過(guò)程中,如果遇到外聯(lián)的樣式聲明和腳本聲明,則暫停文檔解析,創(chuàng)建新的網(wǎng)絡(luò)連接,并開始下載樣式文件和腳本文件;
- 樣式文件下載完成后,構(gòu)建CSSDOM;腳本文件下載完成后,解釋并執(zhí)行,然后繼續(xù)解析文檔構(gòu)建DOM
- 完成文檔解析后,將DOM和CSSDOM進(jìn)行關(guān)聯(lián)和映射,最后將視圖渲染到瀏覽器窗口,在這個(gè)過(guò)程中,腳本文件的下載和執(zhí)行是與文檔解析同步進(jìn)行,也就是說(shuō),它會(huì)阻塞文檔的解析,如果控制得不好,在用戶體驗(yàn)上就會(huì)造成一定程度的影響。
所以我們需要清楚的了解和使用defer和async來(lái)控制外部腳本的執(zhí)行。
作用
- defer:用于開啟新的線程下載腳本文件,并使腳本在文檔解析完成后執(zhí)行。
- async:新增屬性,用于異步下載腳本文件,下載完畢立即解釋執(zhí)行代碼。
區(qū)別
一、<script src="script.js"></script>
沒有 defer 或 async,瀏覽器會(huì)立即加載并執(zhí)行指定的腳本,“立即”指的是在渲染該 script 標(biāo)簽之下的文檔元素之前,也就是說(shuō)不等待后續(xù)載入的文檔元素,讀到就加載并執(zhí)行。
二、<script async src="script.js"></script>
有 async,加載和渲染后續(xù)文檔元素的過(guò)程將和 script.js 的加載與執(zhí)行并行進(jìn)行(異步)。
三、<script defer src="myscript.js"></script>
有 defer,加載后續(xù)文檔元素的過(guò)程將和 script.js 的加載并行進(jìn)行(異步),但是 script.js 的執(zhí)行要在所有元素解析完成之后,DOMContentLoaded 事件觸發(fā)之前完成。