關于script標簽的defer和async

背景

最近開發(fā)的過程中遇到一個問題:頁面中加載了一個改寫fetch的js文件,然后后面使用了fetch發(fā)送請求。發(fā)現(xiàn)在實際上,并沒有實現(xiàn)對fetch的改寫,而是使用了原生的fetch。初步懷疑是由于js的加載順序導致了問題的出現(xiàn),也就是說在使用fetch的代碼執(zhí)行之前,改寫fetch的代碼還未加載執(zhí)行完成,所以沒有實現(xiàn)對它的改寫。
實際上并不是因為這個,而是因為改寫fetch的js文件放在另外一個系統(tǒng)文件中,而這個系統(tǒng)是需要登錄的,但是在本地開發(fā)中,是不做登錄驗證的,即使沒有登錄也不會拉起CAS登錄,所以文件加載失敗了,改寫也沒有成功。
即使如此,還是需要補充一點關于script標簽加載js的知識。

基礎知識

script標簽需要放在body最后,這是開發(fā)中一直堅持的習慣,為什么這樣做呢?因為js的加載和執(zhí)行會阻塞后續(xù)html的解析和渲染。如果一個script標簽放在html中間,當執(zhí)行到這一句時,會停止對html的解析和渲染,轉而進行js的加載和執(zhí)行,結束以后,再繼續(xù)后面的內容。

defer和asnyc

1.defer

這個屬性的用途是表明腳本在執(zhí)行時不會影響頁面的構造。也就是說,腳本會被延遲到整個頁面都解析完畢后再運行。因此,在<script>元素中設置defer屬性,相當于告訴瀏覽器立即下載,但延遲執(zhí)行。

HTML5規(guī)范要求腳本按照它們出現(xiàn)的先后順序執(zhí)行,因此第一個延遲腳本會先于第二個延遲腳本執(zhí)行,而這兩個腳本會先于DOMContentLoaded事件執(zhí)行。在現(xiàn)實當中,延遲腳本并不一定會按照順序執(zhí)行,也不一定會在DOMContentLoad時間觸發(fā)前執(zhí)行,因此最好只包含一個延遲腳本。

2.async

這個屬性與defer類似,都用于改變處理腳本的行為。同樣與defer類似,async只適用于外部腳本文件,并告訴瀏覽器立即下載文件。但與defer不同的是,標記為async的腳本并不保證按照它們的先后順序執(zhí)行。

第二個腳本文件可能會在第一個腳本文件之前執(zhí)行。因此確保兩者之間互不依賴非常重要。指定async屬性的目的是不讓頁面等待兩個腳本下載和執(zhí)行,從而異步加載頁面其他內容。

3.對比

defer async default對比

藍色線代表網(wǎng)絡讀取,紅色線代表執(zhí)行時間,這倆都是針對腳本的;綠色線代表 HTML 解析。
也就是說,對于默認的情況,當解析html過程中遇到了script,會停下對html的解析和渲染,去下載和執(zhí)行js。
當設置了defer后,當遇到script時,會并行下載,等到html解析完成后,再按順序執(zhí)行這些js。
當設置了async時,當遇到script會并行下載,并且誰先下載完就先執(zhí)行誰。
但是需要注意的是,由于各個瀏覽器廠商對于規(guī)定的執(zhí)行標準不同,其實并無法保證defer的情況下js一定是按順序執(zhí)行的,所以最穩(wěn)妥的方法還是將js放到body底部,等待所有html執(zhí)行完畢再進行js的解析執(zhí)行,避免出現(xiàn)執(zhí)行順序錯誤導致的問題。但是如果不考慮 執(zhí)行順序,使用defer可以在解析html時并行加載js,應該是可以節(jié)省加載時間的。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容