1. 程式人生 > >聊聊瀏覽器(webkit)資源載入機制

聊聊瀏覽器(webkit)資源載入機制

一些準備

在開始這個話題之前,我們有必要簡單回顧一下 瀏覽器(webkit)的網頁渲染過程(如果想要詳細瞭解這個過程,可以戳我幾年前寫的一篇文章。):

我們知道,瀏覽器在渲染過程中,如遇到節點需要依賴其他資源(比如:圖片、CSS、JavaScript、video等),瀏覽器會通過網路去載入它們。這其中大部分的資源是非同步載入的,不會阻塞渲染,除了 JavaScript(未被標記為非同步的方式)。

網頁的載入和渲染依賴網路與資源載入,網頁本身是一種資源,它所依賴的 js、css、圖片、視訊等也是資源。而資源的載入涉及網路和資源的快取等機制,而且它們充斥著整個渲染過程。

一、資源

HTML 中支援的資源主要包括以下型別:

  • HTML:HTML 頁面,包括各種各樣的 HTML 元素
  • JavaScript:JavaScript 程式碼,可以內嵌在 HTML 檔案中,也能以單獨的檔案存在
  • CSS 樣式表:CSS 樣式資源,可內嵌在 HTML 檔案中,也可以單獨的單獨檔案形式存在
  • CSS Shader
  • 圖片:各種編碼格式的圖片資源
  • SVG:用於繪製 SVG 的 2D 向量圖形表示
  • 視訊、音訊和字幕:多媒體資源和支援音視訊的字幕檔案(TextTrack)
  • 字型檔案:CSS3 引入的自定義字型檔案
  • XSL 樣式表:使用 XSLT 語言編寫的 XSLT 程式碼檔案

在 webkit 內部,會使用不同的類去表示它們,其對應關係:

資源型別 內部表示類
HTML CachedRawResource
JavaScript CachedScript
CSS 樣式表 CachedCSSStyleSheet
CSS Shader CachedShader
圖片 CachedImage
SVG CachedSVGDocument
字幕 CachedTextTrack
字型檔案 CachedFont
XSL 樣式表 CachedXSLStyleSheet

以上內部表示類均繼承自 CachedResource 類。 聰明的你一定發現了, 這些類名都是以 “Cached” 開頭,這其實是考慮到效率問題二引入的快取機制。所有對資源的請求都會先獲取快取中的資訊,以決定是否向伺服器發起資源請求。

二、資源快取 

資源的快取機制是提高資源使用效率的有效方法。在 webkit 內部,它的基本思想是建立一個資源的快取池(記憶體快取),當需要請求資源時,會先從資源池中查詢是否存在響應的資源。如果存在,則直接使用快取池中的資源。如果不存在,則傳送真正的請求載入資源,收到響應的資源後,webkit 會將其設定到上面提的到資源類中去。

 

這些資源,在 webkit 內部是以 URL 作為 key 去查詢的。因為 URL 是標記資源的唯一性的特徵。

三、資源載入器

webkit 總共有 3 種資源載入器:

  • 針對每種資源型別的特定載入器,該類資源載入器只加載某一種資源。其內部表示有:ImageLoader、FontLoader 等
  • 資源快取機制的資源載入器,特定資源載入器都共享它來插入和查詢快取資源。其內部表示為:CachedResourceLoader
  • 通用資源載入器,當瀏覽器需要從檔案系統或網路載入資源時,會使用該類載入器,但它只負責獲取資源的資料,正因為如此,它也被所有的特定資源載入器所共享。其內部表示為:ResourceLoader

以 ImageLoader 這個特定資源載入器為例,大致可用下圖描述:

結合 chrome 瀏覽器除錯工具,以訪問百度首頁為例,來觀察百度 logo 的請求情況。為防止之前的快取,採用 “清除快取並硬性重新載入” 方式訪問。表現如下:

再正常不過的 200, 沒有 from * cache 標識意味著來源於網路。新開 tab, 再次訪問百度首頁:

發現在 size 列(倒數第二列)多了 “(from disk cache)” 字樣。在此基礎上(不關閉 tab),正常重新整理該頁面: 

聰明的你一定發現 了原來 size 列的 “from disk cache” 變為了 “from memory cache”。顧名思義,兩張圖片的載入方式由從 磁碟快取讀取 變為了 從記憶體快取讀取。摘一段官網上的文件(文件地址):

簡單翻譯:Chrome 使用兩種快取:磁碟快取和高速的記憶體快取。記憶體快取(memory cache)依附於渲染程序,我們可以大致認為一個渲染程序就等於一個 tab。

因此,“from memory cache” 只有在正常重新整理的情況下,才會命中。這也解釋了前面示例中新開啟的 tab 訪問百度首頁,得到的是 “from disk cache”。

四、過程

經過前面的介紹,我們建立起了對 資源、資源快取、資源載入器 的認知。接下來詳細聊聊資源的載入過程。還是以圖片載入為例:

我們都知道,在網頁載入時,如遇到 script 標籤(未宣告非同步),會阻塞渲染。在這種情況下,webkit 會啟動另外一個去遍歷後面的 HTML 網頁,收集需要的資源的 URL,然後傳送請求,以此來避免阻塞。

回到資源快取的話題,前面提到,在 webkit 內部是存在一個 “快取池” 。為了保證在有限空間的快取池內能夠持續的插入新的快取,它使用 LRU 演算法來管理快取。