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