一、在文檔的<head>元素中包含所有JavaScript文件
必須等到全部JavaScript代碼都被下載、解析和執(zhí)行完成之后,才能開始呈現(xiàn)頁面的內(nèi)容。這無疑會導(dǎo)致瀏覽器在呈現(xiàn)頁面時出現(xiàn)明顯的延遲,特別是比較龐大的腳本,將會極大的影響用戶體驗。
為了避免這個問題,一般把全部JavaScript引用放在<body>元素后面。這樣在解析包含的JavaScript代碼之前,頁面的內(nèi)容將完全呈現(xiàn)在瀏覽器中。
二、延遲腳本:設(shè)置defer屬性
腳本會延遲到整個頁面都解析完畢后再運行, 相當于立即下載,但延遲執(zhí)行。延遲腳本按照出現(xiàn)的先后順序執(zhí)行。
<script src="test.js" defer></script>
部分瀏覽器會忽略這個屬性,因此把延遲腳本放在底部仍然是最佳的選擇。
三、異步腳本:設(shè)置async屬性
與defer類似,async只適用于外部腳本文件,并告訴瀏覽器立即下載文件。但與defer不同的是,標記為async的腳本并不保證按照指定它們的先后順序執(zhí)行。
如果不考慮低版本的IE瀏覽器:
使用async屬性即可實現(xiàn)異步加載,即便將加載js的代碼放置于<head>中也沒有影響。
<script src="test.js" async></script>
如果要兼容所有瀏覽器:
如果要兼容老舊的瀏覽器,實踐表明可使用用來動態(tài)注入腳本的腳本加載器。
比如可以使用require.js等實現(xiàn)異步加載。
還有一種方法,就是將引入js的代碼放置于body底部,并帶上async屬性。這雖然在老舊瀏覽器中不會異步加載腳本,但它只阻塞了body結(jié)束標簽之前的DOM解析,這就大大降低了其阻塞影響。而在現(xiàn)代瀏覽器中,腳本將在DOM解析器發(fā)現(xiàn)body尾部的script標簽才進行加載,此時加載屬于異步加載,不會阻塞CSSOM(但其執(zhí)行仍發(fā)生在CSSOM之后)。