高效能JavaScript(載入和執行)
當瀏覽器遇到 <script> 標籤時,它是沒辦法知道 JavaScript 是否會向DOM中新增內容或引入其他元素,甚至關閉某一個標籤。因此這個時候瀏覽器就會停止處理頁面,先執行JavaScript程式碼,然後再繼續解析和渲染頁面。
改善
將<script>標籤放到 <body>的底部,儘量減少對整個頁面下載的影響。
減少<script>標籤的數量,不僅僅是外鏈指令碼,內嵌的指令碼數量同樣也要限制。(合併)
無阻塞指令碼
無阻塞指令碼的祕訣在於,在頁面載入完成後才載入<script>程式碼,這意味著在 window 物件的 load 事件觸發後再下載指令碼
實現方式
在HTML 4 中為 <script> 標籤定義了一個擴充套件屬性:defer。這個屬性在之前是隻有IE4+ 和 Firefox3.5+的瀏覽器支援。不過現在已被所有主流瀏覽器支援。在HTML 5規範中引入了 async 屬性,用於非同步載入指令碼,async 和 defer 的相同點是採用並行下載,在下載過程中不會產生阻塞,區別在於執行時間,async 是載入完成後自動執行,而 defer 需要等待頁面完成後執行。
其中藍色代表js指令碼網路載入時間,紅色代表js指令碼執行時間,綠色代表html解析。
另一種無阻塞載入指令碼的方式是使用 XMLHttpRequest(XHR)物件,用get請求一個檔案,請求好了。然後建立動態指令碼,最後新增進去。缺陷:檔案要再請求頁面的同一個域。不能從cdn下載。
開源無阻塞指令碼載入工具:LazyLoad,LABjs
小結:
介面繪製的時候,每次遇到<script>標籤,頁面都會停下來等待程式碼的下載(外鏈)並執行然後繼續往下處理
優化:
</body>閉合標籤之前,將所有的<script>標籤放到頁面底部,確保在指令碼紙行前頁面已經完成了渲染。
合併指令碼檔案,<script>標籤越少,載入越快,相應也更迅速。不管是外鏈還是內嵌。
多種無阻塞下載JavaScript的方法
- 使用<script> defer,async屬性
- 動態建立<script>元素下載並執行程式碼
- 使用 XHR 物件下載 JavaScript 程式碼並注入程式碼。