Webkit 內(nèi)核初探
點擊藍色“腦洞前端”關(guān)注我喲
加個“星標”,帶你揭開大前端的神秘面紗!
?這是腦洞前端第「101」篇原創(chuàng)文章
作者: 阿吉 校對&整理: lucifer
當下瀏覽器內(nèi)核主要有 Webkit、Blink 等。本文分析注意是自 2001 年 Webkit 從 KHTML 分離出去并開源后,各大瀏覽器廠商魔改 Webkit 的時期,這些魔改的內(nèi)核最終以 Chromium 受眾最多而脫穎而出。本文就以 Chromium 瀏覽器架構(gòu)為基礎,逐層探入進行剖析。
引子
這里以一個面試中最常見的題目從 URL 輸入到瀏覽器渲染頁面發(fā)生了什么?開始。
這個很常見的題目,涉及的知識非常廣泛。大家可先從瀏覽器監(jiān)聽用戶輸入開始,瀏覽器解析 url 的部分,分析出應用層協(xié)議 是 HTTPS 還是 HTTP 來決定是否經(jīng)過會話層 TLS 套接字,然后到 DNS 解析獲取 IP,建立 TCP 套接字池 以及 TCP 三次握手,數(shù)據(jù)封裝切片的過程,瀏覽器發(fā)送請求獲取對應數(shù)據(jù),如何解析 HTML,四次揮手等等等等。這個回答理論上可以非常詳細,遠比我提到的多得多。
本文試圖從瀏覽器獲取資源開始探究 Webkit。如瀏覽器如何獲取資源,獲取資源時 Webkit 調(diào)用了哪些資源加載器(不同的資源使用不同的加載器),Webkit 如何解析 HTML 等入手。想要從前端工程師的角度弄明白這些問題,可以先暫時拋開 C++源碼,從瀏覽器架構(gòu)出發(fā),做到大致了解。之后學有余力的同學再去深入研究各個底層細節(jié)。
本文的路線循序漸進,從 Chromium 瀏覽器架構(gòu)出發(fā),到 Webkit 資源下載時對應的瀏覽器獲取對應資源如 HTML、CSS 等,再到 HTML 的解析,再到 JS 阻塞 DOM 解析而產(chǎn)生的 Webkit 優(yōu)化 引出瀏覽器多線程架構(gòu),繼而出于安全性和穩(wěn)定性的考慮引出瀏覽器多進程架構(gòu)。
一. Chromium 瀏覽器架構(gòu)

(Chromium 瀏覽器架構(gòu))
我們通常說的瀏覽器內(nèi)核,指的是渲染引擎。
WebCore 基本是共享的,只是在不同瀏覽器中使用 Webkit 的實現(xiàn)方式不同。它包含解析 HTML 生成 DOM、解析 CSS、渲染布局、資源加載器等等,用于加載和渲染網(wǎng)頁。
JS 解析可以使用 JSCore 或 V8 等 JS 引擎。我們熟悉的谷歌瀏覽器就是使用 V8。比如比較常見的有內(nèi)置屬性 [[scope]] 就僅在 V8 內(nèi)部使用,用于對象根據(jù)其向上索引自身不存在的屬性。而對外暴露的 API,如 __proto__ 也可用于更改原型鏈。實際上 __proto__ 并不是 ES 標準提供的,它是瀏覽器提供的(瀏覽器可以不提供,因此如果有瀏覽器不提供的話這也并不是 b ug)。
Webkit Ports 是不共享的部分。它包含視頻、音頻、圖片解碼、硬件加速、網(wǎng)絡棧等等,常用于移植。
同時,瀏覽器是多進程多線程架構(gòu),稍后也會細入。
在解析 HTML 文檔之前,需要先獲取資源,那么資源的獲取在 Webkit 中應該如何進行呢?
二.Webkit 資源加載
HTTP 是超文本傳輸協(xié)議,超文本的含義即包含了文本、圖片、視頻、音頻等等。其對應的不同文件格式,在 Webkit 中 需要調(diào)用不同的資源加載器,即 特定資源加載器。
而瀏覽器有四級緩存,Disk Cache 是我們最常說的通過 HTTP Header 去控制的,比如強緩存、協(xié)商緩存。同時也有瀏覽器自帶的啟發(fā)式緩存。而 Webkit 對應使用的加載器是資源緩存機制的資源加載器 CachedResoureLoader 類。
如果每個資源加載器都實現(xiàn)自己的加載方法,則浪費內(nèi)存空間,同時違背了單一職責的原則,因此可以抽象出一個共享類,即通用資源加載器 ResoureLoader 類。Webkit 資源加載使用了三類加載器:「特定資源加載器,資源緩存機制的資源加載器 CachedResoureLoader 和 通用資源加載器 ResoureLoader」。
既然說到了緩存,那不妨多談一點。
資源既然緩存了,那是如何命中的呢?答案是根據(jù)資源唯一性的特征 URL。資源存儲是有一定有效期的,而這個有效期在 Webkit 中采用的就是 LRU 算法。那什么時候更新緩存呢?答案是不同的緩存類型對應不同的緩存策略。我們知道緩存多數(shù)是利用 HTTP 協(xié)議減少網(wǎng)絡負載的,即強緩存、協(xié)商緩存。但是如果關(guān)閉緩存了呢?比如 HTTP/1.0 Pragma:no-cache 和 HTTP/1.1 Cache-Control: no-cache。此時,對于 Webkit 來說,它會清空全局唯一的對象 MemoryCache 中的所有資源。
資源加載器內(nèi)容先到這里。瀏覽器架構(gòu)是多進程多線程的,其實多線程可以直接體現(xiàn)在資源加載的過程中,在 JS 阻塞 DOM 解析中發(fā)揮作用,下面我們詳細講解一下。
三.瀏覽器架構(gòu)
瀏覽器是多進程多線程架構(gòu)。
對于瀏覽器來講,從網(wǎng)絡獲取資源是非常耗時的。從資源是否阻塞渲染的角度,對瀏覽器而言資源僅分為兩類:「阻塞渲染」如 JS 和 「不阻塞渲染」如圖片。
我們都知道 JS 阻塞 DOM 解析,反之亦然。然而對于阻塞,Webkit 不會傻傻等著浪費時間,它在內(nèi)部做了優(yōu)化:啟動另一個線程,去遍歷后續(xù)的 HTML 文檔,收集需要的資源 URL,并發(fā)下載資源。最常見的比如
