瀏覽器是怎樣載入js代碼的?

HTML中有對js文件的外部引用,那麼當這個HTML文件交給瀏覽器時,瀏覽器會展示這個頁面,但是這個時候js文件還儲存在伺服器端,那麼瀏覽器是怎樣將這個js文件從伺服器上載入到本地的?整個的過程是怎樣的?


就像正常的下載文件一樣。把服務的js文件下載下來,然後在本地瀏覽器執行。

另外你需要補充一下瀏覽器載入、解析、渲染的一些知識。複製一下我之前整理的筆記。

瀏覽器載入

  • 載入過程

    當瀏覽器獲得一個html文件時,會」自上而下「載入,並在載入過程中進行解析渲染。

    載入過程中遇到外部css文件,瀏覽器另外發出一個請求,來獲取css文件。

    遇到圖片資源,瀏覽器也會另外發出一個請求,來獲取圖片資源。這是非同步請求,並不會影響html文檔進行載入。

    但是當文檔載入過程中遇到js文件,html文檔會掛起渲染(載入解析渲染同步)的線程,不僅要等待文檔中js文件載入完畢,還要等待解析執行完畢,才可以恢復html文檔的渲染線程。
  • 載入外聯js和css的阻塞情況

一個不太嚴謹但方便記憶的口訣:JS 全阻塞,CSS 半阻塞

    • JS 會阻塞後續 DOM 解析以及其它資源(如 CSS,JS 或圖片資源)的載入。
    • CSS不阻塞DOM的載入和解析(它只阻塞DOM的渲染呈現。這裡談載入),不會阻塞其它資源(如圖片)的載入,但是會阻塞 後續JS 文件的執行(原因之一是,js執行代碼可能會依賴到css樣式。css只阻塞執行而不阻塞js的載入)。
    • 鑒於上面的特性,當css後面存在js的時候,css會間接地阻塞js後面資源的載入(css阻塞js,js阻塞其他資源 )。
    • 現代瀏覽器會進行 prefetch 優化,瀏覽器在獲得 html 文檔之後會對頁面上引用的資源進行提前下載

外聯js文件使用defer屬性和asyn可以達到非同步非阻塞載入的效果,由於現代瀏覽器都存在 prefetch,所以 defer, async 可能並沒有太多的用途,可以作為了解擴展知識,僅僅將腳本文件放到 body 底部(但還是在&之前)就可以起到很不錯的優化效果(遵循先解析再渲染再執行script這個順序)。當把js放在最後的時候,其實瀏覽器將自動忽略&標籤,從而自動在最後的最後補上&

瀏覽器解析

  • 1、瀏覽器通過請求的 URL 進行域名解析,向伺服器發起請求,接收文件(HTML、CSS、JS、Images等等)。
  • 2、HTML 文件載入後,開始構建 DOM Tree(DOM樹)
  • 3、CSS 樣式文件載入後,開始解析和構建 CSS Rule Tree
  • 4、Javascript 腳本文件載入後, 通過 DOM API 和 CSSOM API 來操作 DOM Tree 和 CSS Rule Tree

瀏覽器渲染

  • 1、瀏覽器引擎通過 DOM Tree 和 CSS Rule Tree 構建 Rendering Tree(渲染樹)
  • 2、布局階段——在屏幕上繪製渲染樹中的所有節點的幾何屬性,比如: 位置,寬高,大小等等,這個過程稱為 Flow 或 Layout 。
  • 3、繪製元素——繪製所有節點的可視屬性。
  • 4、合併渲染層——把以上繪製的所有圖層(類似於PhotoShop中的「圖層」)合併,最終輸出一張圖片

其中的階段3、4可稱之為Paint

Repaint和Reflow

當用戶在瀏覽網頁時進行交互或通過 js 腳本改變頁面結構時,以上的部分操作有可能重複運行,此過程稱為 Repaint 或 Reflow。

  • Repaint

當元素改變的時候,將不會影響元素在頁面當中的位置(比如 background-color, border-color, visibility),瀏覽器僅僅會應用新的樣式重繪此元素,此過程稱為 Repaint。

  • Reflow

當元素改變的時候,將會影響文檔內容或結構,或元素位置,此過程稱為 Reflow。( HTML 使用的是 flow based layout ,也就是流式布局,所以,如果某元件的幾何尺寸發生了變化,需要重新布局,也就叫 Reflow。)

Reflow 的成本比 Repaint 的成本高得多的多。我們應當盡量避免Reflow。

如何優化瀏覽器渲染過程

  • 1、創建有效的 HTML 和 CSS ,不要忘記指定文檔編碼,比如&
  • 2、CSS 樣式應該包含在 &中, Javascript 腳本出現在&末尾。
  • 3、減少 CSS 嵌套層級和選擇適當的選擇器,可參考 如何提升 CSS 選擇器性能。
  • 4、不要通過 JS 逐條修改 DOM 的樣式,提前定義好 CSS 的 Class 進行操作。
  • 5、盡量減少將 DOM 節點屬性值放在循環當中,會導致大量讀寫此屬性值。
  • 6、儘可能的為產生動畫的 HTML 元素使用 fixed 或 absolute 的 position ,那麼修改他們的 CSS 是不會 Reflow 的。


http://www.jianshu.com/p/c9049adff5ec


從伺服器端來說,html和js是同一種東西。都是文本文件,最多只是在返回時有不同的mimetype。

這點其實在你本地用客戶端編輯的時候應該也很明白。

區別是在瀏覽器怎麼去執行這個已經下載好的代碼。

對於瀏覽器來說,html文件會分解為一個包含有數據的xml文件,從這個xml文件中解析出各種數據,再按順序進行解析執行。

普通來說,如果通過 script節點的src屬性引入,同時type為"text/javascript"的,就在下載文件後把文件內容當作js腳本來嘗試執行。

如果script的type不為text/javascript,內容是不會當作js來執行的,典型如jquery時代各種模板都會放在&

基本就是

解析html文件-&>發起請求-&>解析域名-&>申請相應請求頭/正文-&>訪問對應伺服器埠-&>應用程序響應-&>生成響應頭/正文-&>瀏覽器根據相應頭進行相應處理-&>瀏覽器把正文拋給腳本解釋器執行。

對於所有的http請求其實都一樣。


和 http 的處理一樣。下載回來。之後扔給 js 解釋器運行。


當然準確的說法是取決於渲染過程

一般來說比較古老的瀏覽器會向script標籤所指定的url發出http get請求,並且在繼續渲染之前會等待這段腳本的下載和執行。

新瀏覽器在會復用當前的tcp連接(協議為http/1.1且伺服器支持pipeline),並且可能會提前進行某些後面的渲染環節

http/2的話,那麼默認是pipeline,而且伺服器的響應可能會在請求之前到達

但是——如果用戶願意,瀏覽器是完全可以不去載入這個標籤的(比如通過userscript之類的手段),而且有些不支持script的瀏覽器也不會去下載


百度,面試常考


看你這個js是非同步載入還是同步載入:

1、同步載入,如&


推薦閱讀:

遊戲伺服器架構和web伺服器架構的區別?
如何在使用 Linux 命令查找當前目錄底下的文件夾的子目錄中的某個文件?
如何一步步學習開發伺服器(nginx)?

TAG:Web開發 | 前端開發 | JavaWeb | Web伺服器 |