天天看點

js腳本加載

浏覽器的核心是兩部分:渲染引擎和 JavaScript 解釋器(又稱 JavaScript 引擎)。

js腳本加載

浏覽器加載 JavaScript 腳本,主要通過<script>元素完成。正常的網頁加載流程是這樣的。

  • 浏覽器一邊下載下傳 HTML 網頁,一邊開始解析。也就是說,不等到下載下傳完,就開始解析。
  • 解析過程中,浏覽器發現 <script>元素,就暫停解析,把網頁渲染的控制權轉交給 JavaScript 引擎。
  • 如果<script>元素引用了外部腳本,就下載下傳該腳本再執行,否則就直接執行代碼。
  • JavaScript 引擎執行完畢,控制權交還渲染引擎,恢複往下解析 HTML 網頁。

如果外部腳本加載時間很長(一直無法完成下載下傳),那麼浏覽器就會一直等待腳本下載下傳完成,造成網頁長時間失去響應,浏覽器就會呈現“假死”狀态,這被稱為“阻塞效應”。

為了避免這種情況,較好的做法是将<script>标簽都放在頁面底部,而不是頭部。這樣即使遇到腳本失去響應,網頁主體的渲染也已經完成了,使用者至少可以看到内容,而不是面對一張空白的頁面。如果某些腳本代碼非常重要,一定要放在頁面頭部的話,最好直接将代碼寫入頁面,而不是連接配接外部腳本檔案,這樣能縮短加載時間.

此外,對于來自同一個域名的資源,比如腳本檔案、樣式表檔案、圖檔檔案等,浏覽器一般有限制,同時最多下載下傳6~20個資源,即最多同時打開的 TCP 連接配接有限制,這是為了防止對伺服器造成太大壓力。如果是來自不同域名的資源,就沒有這個限制。是以,通常把靜态檔案放在不同的域名之下,以加快下載下傳速度。

defer屬性

為了解決腳本檔案下載下傳阻塞網頁渲染的問題,一個方法是對<script>元素加入defer屬性。它的作用是延遲腳本的執行,等到 DOM 加載生成後,再執行腳本

<script src="a.js" defer></script>
<script src="b.js" defer></script>
           

defer屬性的運作流程如下:

1. 浏覽器開始解析 HTML 網頁。

2.解析過程中,發現帶有defer屬性的<script>元素。

3.浏覽器繼續往下解析 HTML 網頁,同時并行下載下傳<script>元素加載的外部腳本。

4.浏覽器完成解析 HTML 網頁,此時再回過頭執行已經下載下傳完成的腳本。

有了defer屬性,浏覽器下載下傳腳本檔案的時候,不會阻塞頁面渲染。下載下傳的腳本檔案在DOMContentLoaded事件觸發前執行(即剛剛讀取完标簽),而且可以保證執行順序就是它們在頁面上出現的順序。

async屬性

解決“阻塞效應”的另一個方法是對<script>元素加入async屬性

<script src="a.js" async></script>
<script src="b.js" async></script>
           

async屬性的作用是,使用另一個程序下載下傳腳本,下載下傳時不會阻塞渲染。

1.浏覽器開始解析 HTML 網頁。

2.解析過程中,發現帶有async屬性的script标簽。

3.浏覽器繼續往下解析 HTML 網頁,同時并行下載下傳<script>标簽中的外部腳本。

4.腳本下載下傳完成,浏覽器暫停解析 HTML 網頁,開始執行下載下傳的腳本。

5.腳本執行完畢,浏覽器恢複解析 HTML 網頁。

async屬性可以保證腳本下載下傳的同時,浏覽器繼續渲染。需要注意的是,一旦采用這個屬性,就無法保證腳本的執行順序。哪個腳本先下載下傳結束,就先執行那個腳本。另外,使用async屬性的腳本檔案裡面的代碼,不應該使用document.write方法

defer屬性和async屬性到底應該使用哪一個?

一般來說,如果腳本之間沒有依賴關系,就使用async屬性,如果腳本之間有依賴關系,就使用defer屬性。如果同時使用async和defer屬性,後者不起作用,浏覽器行為由async屬性決定。

加載使用的協定

如果不指定協定,浏覽器預設采用 HTTP 協定下載下傳。

<script src="example.js"></script>
           

上面的example.js預設就是采用 HTTP 協定下載下傳,如果要采用 HTTPS 協定下載下傳,必需寫明。

<script src="https://example.js"></script>
           

但是有時我們會希望,根據頁面本身的協定來決定加載協定,這時可以采用下面的寫法。

<script src="//example.js"></script>


           

轉載: https://wangdoc.com/javascript/bom/engine.html#%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86

繼續閱讀