導(dǎo)語(yǔ):本文從市面主流的瀏覽器及相應(yīng)的內(nèi)核引擎開始,介紹了Chromium為代表的瀏覽器架構(gòu)及Blink內(nèi)核的功能架構(gòu)。Chromium為多進(jìn)程架構(gòu),用戶從啟動(dòng)運(yùn)行瀏覽器后,先后經(jīng)過(guò)頁(yè)面導(dǎo)航、渲染、資源加載、樣式計(jì)算、布局、繪制、合成到柵格化,最后完成GPU展示。而頁(yè)面渲染完成后,瀏覽器如何響應(yīng)頁(yè)面操作事件也進(jìn)行了深入的介紹。良心推薦! 本文第二至五部分內(nèi)容根據(jù) Mariko Kosaka 的英文原版《Inside look at modern web browser》,進(jìn)行翻譯、理解、總結(jié)提煉、條理化、加入應(yīng)用示例、進(jìn)行相關(guān)知識(shí)補(bǔ)充擴(kuò)展而來(lái)。
一、瀏覽器概論瀏覽器經(jīng)歷了很多年的發(fā)展,瀏覽器引擎也在不停地迭代和演進(jìn)。從PC時(shí)代到移動(dòng)端,以獨(dú)立瀏覽器的形態(tài)還是以系統(tǒng)WebView組件內(nèi)嵌的形態(tài)存在,在互聯(lián)網(wǎng)的生態(tài)系統(tǒng)中一直扮演著重要的角色。了解瀏覽器及其原理可以讓我們打開另一個(gè)世界。
1.瀏覽器引擎
以下是市面留存的主流瀏覽器的引擎介紹。
1.1 瀏覽器引擎
Trident:IE瀏覽器引擎
Gecko:Firefox瀏覽器引擎
Presto:Opera瀏覽器引擎
Webkit:Safari,Google Chrome瀏覽器引擎。
1) Chromium:基于webkit,08年開始作為Chrome的引擎,Chromium瀏覽器是Chrome的實(shí)驗(yàn)版,實(shí)驗(yàn)新特性。 2) Webkit2:2010年隨OS X Lion一起面世。WebCore層面實(shí)現(xiàn)進(jìn)程隔離與Google的沙箱設(shè)計(jì)存在沖突。 3) Blink:基于Webkit2分支,13年谷歌開始作為Chrome 28的引擎集成在Chromium瀏覽器里。Android的WebView同樣基于Webkit2。 1.2 微軟瀏覽器目前PC場(chǎng)景操作系統(tǒng)仍是windows一統(tǒng)天下,對(duì)桌面用戶來(lái)說(shuō),雖然IE的市場(chǎng)份額在下降,但是IE曾經(jīng)也風(fēng)光過(guò)。IE內(nèi)核以Trident為主,最新的Edge也兼容了Chromium內(nèi)核。 Microsoft Edge:內(nèi)核為:EDGE,Windows 10默認(rèn)瀏覽器,不能單獨(dú)下載安裝。兼容Chromium內(nèi)核,同時(shí)保留EDGE內(nèi)核來(lái)兼容企業(yè)網(wǎng)站
Internet Explorer 11:Windows 8.1,引擎Trident 7.0
Internet Explorer 10:Windows 8默認(rèn)瀏覽器,引擎Trident
Internet Explorer 9
Internet Explorer 8:Windows 7集成
Internet Explorer 7:Windows Vista集成,2016年停止支持
Internet Explorer 6:2014年停止支持
2. 瀏覽器架構(gòu)
目前chromium瀏覽器的架構(gòu)主要由下以幾個(gè)部分構(gòu)成。
以下為架構(gòu)的介紹:
操作系統(tǒng):WebKit可以運(yùn)行在不同的操作系統(tǒng)上,如Chromium瀏覽器支持Windows、Linux、Android等系統(tǒng);
第三方庫(kù):這些庫(kù)是WebKit運(yùn)行的基礎(chǔ),包括2D圖形庫(kù)、3D圖形庫(kù)、網(wǎng)絡(luò)庫(kù)、存儲(chǔ)庫(kù)、音視頻庫(kù)等;
WebCore:WebKit加載和渲染網(wǎng)頁(yè)的基礎(chǔ),是不同瀏覽器所使用的WebKit中共享的部分,包括HTML解析器、CSS解析器、SVG、布局、渲染樹等等;
JavaScript引擎:JavaScript解析器,WebKit默認(rèn)的引擎是JavaScriptCore,Google的Blink為V8引擎;
WebKit Ports:WebKit中的移植部分,包括網(wǎng)絡(luò)棧、音視頻解碼、硬件加速等模塊,這部分對(duì)WebKit的功能和性能影響比較大。
WebKit嵌入式接口:WebKit對(duì)外暴露的接口層,這個(gè)接口是提供給瀏覽器調(diào)用的,如給chromium調(diào)用,因?yàn)榻涌谂c具體的移植也有關(guān)系,所以中間會(huì)有一個(gè)WebKit綁定層
JavaScriptCore(用于Safari)
JavaSript Parser,JSON Parser
字節(jié)編譯器:使用內(nèi)部字節(jié)碼格式
匯編程序:在運(yùn)行時(shí)使用代碼修補(bǔ) - >它需要可寫代碼內(nèi)存
數(shù)據(jù)流圖:基于編譯時(shí)推測(cè)優(yōu)化生成代碼的新舉措
解釋器:運(yùn)行生成的字節(jié)碼
Regexp引擎:支持JIT
垃圾收集器:標(biāo)記和掃描
運(yùn)行時(shí):所有JS全局對(duì)象(日期,字符串,數(shù)字等)
調(diào)試器,Profiler
WebCore
資源加載器:HTML和XML解析器,DOM
SVG和SMIL
CSS:分析器,選擇器,動(dòng)畫
渲染和布局
綁定生成器:IDL文件:JSC,V8,ObjC
WebInspector
平臺(tái)集成:圖形,字體,聲音,視頻
相關(guān)資料
Blink內(nèi)核:https://src.chromium.org/viewvc
2.1 多進(jìn)程架構(gòu)
圖片引自chromium-design-doc https://www.chromium.org/developers/design-documents/multi-process-architecture 2.1.1 Chromium多進(jìn)程架構(gòu)早期的web瀏覽器頁(yè)面行為不當(dāng)、瀏覽器錯(cuò)誤、瀏覽器插件錯(cuò)誤都會(huì)引起整個(gè)瀏覽器或當(dāng)前運(yùn)行的選項(xiàng)卡關(guān)閉。因此將chromium應(yīng)用程序放在相互隔離的獨(dú)立的進(jìn)程中:
單個(gè)程序崩潰不會(huì)損害其他應(yīng)用程序
不影響操作系統(tǒng)完整性
每個(gè)用戶不能訪問其他用戶數(shù)據(jù)(內(nèi)存保護(hù)、訪問控制)
2.1.2 架構(gòu)組成
UI主進(jìn)程:頁(yè)面選項(xiàng)卡、插件進(jìn)程作為瀏覽器進(jìn)程。
渲染進(jìn)程:特定選項(xiàng)卡作為渲染進(jìn)程(渲染器),使用Blink(Webkit)開源布局引擎解釋和布局HTML。
2.1.3 渲染過(guò)程管理
RenderProcess:每個(gè)渲染進(jìn)程都有一個(gè)全局對(duì)象,管理與父瀏覽器的通信并維護(hù)全局狀態(tài)
RenderProcessHost:瀏覽器為每個(gè)渲染進(jìn)程維護(hù)相應(yīng)的渲染進(jìn)程宿主,為每個(gè)渲染器管理瀏覽器狀態(tài)和IPC(IPC已棄用,最新用Mojo)通信
RenderView:每個(gè)渲染進(jìn)程有一或多個(gè)RenderView對(duì)象,對(duì)應(yīng)內(nèi)容選項(xiàng)卡。RenderProcessHost為渲染器的每個(gè)視圖(RenderView)維護(hù)一個(gè)RenderViewHost。每個(gè)視圖用一個(gè)ID區(qū)分。
2.1.4 運(yùn)行流程
渲染進(jìn)程共享:開啟瀏覽器新窗口或新選項(xiàng)卡時(shí),創(chuàng)建新的瀏覽器進(jìn)程,并創(chuàng)建RenderView。不同頁(yè)面/iframe可共享同個(gè)渲染進(jìn)程。
崩潰監(jiān)視:瀏覽器的IPC連接會(huì)監(jiān)視進(jìn)程句柄,如句柄對(duì)應(yīng)的渲染進(jìn)程已崩潰,會(huì)向標(biāo)簽發(fā)送通知,瀏覽器會(huì)顯示“悲傷標(biāo)簽”
沙箱運(yùn)行:渲染器在單獨(dú)的進(jìn)程中運(yùn)行,通過(guò)沙箱限制其對(duì)系統(tǒng)資源(文件、網(wǎng)絡(luò)、顯示、擊鍵)的訪問,而須通過(guò)父瀏覽器進(jìn)程訪問
內(nèi)存交回:進(jìn)程最小化、隱藏的選項(xiàng)卡將其內(nèi)存自動(dòng)放入“可用內(nèi)存”,內(nèi)存不足時(shí),windows會(huì)將該可用內(nèi)存數(shù)據(jù)寫磁盤,內(nèi)存被用于更高優(yōu)先級(jí)任務(wù),以提高可見程序的響應(yīng)速度。
2.1.5 插件擴(kuò)展第三方編寫的NPAPI插件因存在不穩(wěn)定,同時(shí)需控制對(duì)系統(tǒng)資源的訪問,在各自獨(dú)立的進(jìn)程中運(yùn)行,與渲染器分開。 插件設(shè)計(jì)文檔:https://www.chromium.org/developers/design-documents/plugin-architecture 2.2 Webkit(Blink)架構(gòu)Blink是Web平臺(tái)的渲染引擎,實(shí)現(xiàn)了瀏覽器選項(xiàng)卡中呈現(xiàn)的內(nèi)容:
HTML:實(shí)現(xiàn)Web平臺(tái)規(guī)范,HTML規(guī)范(DOM、CSS、Web IDL)
JavaScript:嵌入V8并運(yùn)行JavaScript
網(wǎng)絡(luò):從底層網(wǎng)絡(luò)堆棧請(qǐng)求資源
渲染:構(gòu)建DOM樹,計(jì)算樣式和布局,嵌入合成器并繪制圖形
通過(guò)內(nèi)容公共Api對(duì)外提供公共能力。
2.2.1 Blink的運(yùn)行流程多進(jìn)程架構(gòu),有一個(gè)瀏覽器進(jìn)程和N個(gè)沙盒渲染器進(jìn)程,Blink在沙盒渲染中運(yùn)行。瀏覽器選項(xiàng)卡、iframe可共享同個(gè)渲染器進(jìn)程。 沙箱運(yùn)行:在沙箱中,須通過(guò)父瀏覽器進(jìn)程來(lái)調(diào)度使用資源(文件訪問、網(wǎng)絡(luò)、音視頻播放、用戶配置文件讀取(cookie,密碼)等。Blink將瀏覽器進(jìn)程抽象為一組服務(wù),使用Mojo與服務(wù)、瀏覽器進(jìn)程交互。 2.2.2 渲染進(jìn)程中的線程
1個(gè)主線程:運(yùn)行JavaScript、DOM、CSS、樣式布局計(jì)算
N個(gè)工作線程:運(yùn)行Web Worker,ServiceWorker,Worklet
內(nèi)部線程:Blink和V8會(huì)創(chuàng)建幾個(gè)線程處理web audio,數(shù)據(jù)庫(kù),GC等
跨線程通信:使用PostTask API,不鼓勵(lì)共享內(nèi)存編程除非性能原因。
2.2.3 Blink的運(yùn)行和退出
運(yùn)行:任何使用Blink的場(chǎng)景都需調(diào)用 BlinkInitializer::Initialize() 初始化
退出:渲染器被強(qiáng)制退出,而不會(huì)被清理
2.2.4 Blink的項(xiàng)目代碼結(jié)構(gòu)
platform:低級(jí)功能集合,如單片內(nèi)核、幾何、圖形工具
core:core與DOM緊密結(jié)合
web:實(shí)現(xiàn)規(guī)范中的web平臺(tái)功能
modules:包含獨(dú)立的功能,如web audio,indexed db等。
bindings / core:大量使用V8 API
controller:一組使用core、modules的高級(jí)庫(kù),如devtools。
依賴關(guān)系:Chromium -> controller -> modules / bindings -> core / bindings -> platform -> 低級(jí)單元(base、V8、cc)
2.2.5 platform內(nèi)部構(gòu)成1) WTF:統(tǒng)一編碼原語(yǔ),如WTF::Vector, WTF::HashSet, WTF::HashMap, WTF::String and WTF::AtomicString來(lái)代替std:vector 等。 2) 內(nèi)存管理:a. PartitionAlloc b.Oilpan(Blink GC) c.malloc/free/new/delete 3) 任務(wù)調(diào)度:為提高渲染引擎的響應(yīng),應(yīng)執(zhí)行異步。所有任務(wù)都應(yīng)發(fā)布到Blink Scheduler任務(wù)隊(duì)列,指定正確類型并設(shè)置優(yōu)先級(jí),以使得能巧妙地安排任務(wù)。 4) Page/Frame/Document/ExecutionContext/DOMWindow 分別對(duì)應(yīng)選項(xiàng)卡、iframe、window.document、主線程和工作線程上下文、JavaScript中的窗口對(duì)象。
渲染進(jìn)程中各種數(shù)量關(guān)系
渲染器進(jìn)程/Page = 1/N
頁(yè)數(shù)/幀= 1/M
框架/DOMWindow/文檔(或ExecutionContext)= 1/1/1 (會(huì)隨時(shí)變化)
5) 進(jìn)程外iframe 站點(diǎn)隔離:為每個(gè)站點(diǎn)創(chuàng)建一個(gè)渲染器進(jìn)程(相同一二級(jí)域名)。跨站點(diǎn)由兩個(gè)渲染器托管。 6) 分離的iframe/文件
doc = iframe.contentDocumentiframe.remove() //iframe 與 dom 樹分離doc.createElement('div'); //仍可在分離的框架上運(yùn)行腳本 左滑可查看完整代碼,下同
7) Web IDL綁定
8) V8
Isolate:一一對(duì)應(yīng)物理線程。主線程、工作線程都有自己的獨(dú)立線程。
Context:對(duì)應(yīng)全局對(duì)象,如為Frame時(shí)對(duì)應(yīng)Frame的窗口對(duì)象,每個(gè)幀都有自己的窗口對(duì)象
World:支持Chrome擴(kuò)展程序內(nèi)容腳本
關(guān)系:一個(gè)frame = N個(gè)窗口對(duì)象 = 用于N個(gè)world。Context對(duì)應(yīng)該窗口對(duì)象 V8的API低級(jí)且難以使用,在platform/bindings中提供很多V8 API輔助類。每個(gè)C++ DOM對(duì)象,如Node都有其對(duì)應(yīng)的V8包裝器。V8包裝器對(duì)應(yīng)的C++ DOM對(duì)象具有強(qiáng)引用。C++ DOM對(duì)象只對(duì)V8包裝器弱引用。
2.3 V8V8是Google的開源高性能JavaScript和WebAssembly引擎,用C++編寫,它實(shí)現(xiàn)ECMAScript和WebAssembly,可獨(dú)立運(yùn)行或嵌入到任何C++應(yīng)用程序中,如Chrome和Node.js。
相關(guān)資料 ECMAScript:https://tc39.es/ecma262/ WebAssembly:https://webassembly.github.io/spec/core/
二、Chrome的多進(jìn)程架構(gòu)
注意:以下內(nèi)容根據(jù) Mariko Kosaka 的英文原版《Inside look at modern web browser》(見參考文獻(xiàn)),進(jìn)行翻譯、理解、總結(jié)提煉、條理化、加入應(yīng)用示例、進(jìn)行相關(guān)知識(shí)補(bǔ)充擴(kuò)展而來(lái)。
1. 背景:計(jì)算機(jī)的核心是CPU和GPU
CPU:Center Processing Unit,同時(shí)支持并行、串行操作,需很強(qiáng)通用性處理不同數(shù)據(jù)類型、要支持復(fù)雜通用邏輯判斷,需引入大量分支和中斷處理,結(jié)構(gòu)異常復(fù)雜。 GPU:Graphics Processing Uint,專為執(zhí)行圖形渲染必須的復(fù)雜的數(shù)學(xué)和幾何計(jì)算而設(shè)計(jì)。
圖片引自Mariko Kosaka的《Inside look at modern web browser》
圖片引自Mariko Kosaka的《Inside look at modern web browser》
三層計(jì)算機(jī)體系結(jié)構(gòu) 圖片引自Mariko Kosaka的《Inside look at modern web browser》
2. 基礎(chǔ):在Process和Thread執(zhí)行程序
啟動(dòng)應(yīng)用程序時(shí),創(chuàng)建一個(gè)進(jìn)程,并提供”slab”內(nèi)存,所有應(yīng)用程序狀態(tài)保存在該專用內(nèi)存中,關(guān)閉程序時(shí),系統(tǒng)釋放內(nèi)存。
應(yīng)用程序可能會(huì)創(chuàng)建多個(gè)線程完成工作任務(wù)。
圖片引自Mariko Kosaka的《Inside look at modern web browser》
圖片引自Mariko Kosaka的《Inside look at modern web browser》
3. 瀏覽器架構(gòu)
瀏覽器架構(gòu)沒有統(tǒng)一標(biāo)準(zhǔn)規(guī)范,不同瀏覽器可能使用不同線程或多個(gè)不同進(jìn)程來(lái)構(gòu)建web。少數(shù)線程間通過(guò)IPC通信。
3.1 不同瀏覽器實(shí)現(xiàn)的體系結(jié)構(gòu)
圖片引自Mariko Kosaka的《Inside look at modern web browser》
3.2 Chrome的多進(jìn)程架構(gòu)
圖片引自Mariko Kosaka的《Inside look at modern web browser》
4. 不同進(jìn)程作用
瀏覽器:控制應(yīng)用程序chrome部分,包括地址欄,書簽,后退和前進(jìn)按鈕。及處理Web瀏覽器的不可見特權(quán)部分,例如網(wǎng)絡(luò)請(qǐng)求和文件訪問
渲染:控制顯示網(wǎng)站的選項(xiàng)卡內(nèi)的任何內(nèi)容
插件:控制網(wǎng)站使用的任何插件,例如flash。
GPU:獨(dú)立于其他進(jìn)程處理GPU任務(wù)。它被分成不同的進(jìn)程,因?yàn)镚PU處理來(lái)自多個(gè)應(yīng)用程序的請(qǐng)求并將它們繪制在同表面中。
其他進(jìn)程:瀏覽器右上角更多 -> 更多工具 -> 任務(wù)管理器,查看其他進(jìn)程,如實(shí)用程序網(wǎng)絡(luò)服務(wù)、輔助框架
圖片引自Mariko Kosaka的《Inside look at modern web browser》
5. 多進(jìn)程架構(gòu)
優(yōu)點(diǎn):
防一個(gè)頁(yè)面崩潰影響整個(gè)瀏覽器
安全性和沙箱:操作系統(tǒng)提供了限制進(jìn)程權(quán)限的方法,因此瀏覽器可以從某些功能中對(duì)某些進(jìn)程進(jìn)行沙箱處理。如任意訪問文件
進(jìn)程有自己的私有內(nèi)存空間,可以擁有更多的內(nèi)存。為了節(jié)省內(nèi)存,Chrome限制了它可以啟動(dòng)的進(jìn)程數(shù)量。限制因設(shè)備的內(nèi)存和CPU功率而異,但當(dāng)Chrome達(dá)到限制時(shí),它會(huì)在一個(gè)進(jìn)程中開始從同一站點(diǎn)運(yùn)行多個(gè)選項(xiàng)卡
圖片引自Mariko Kosaka的《Inside look at modern web browser》
6. 服務(wù)化 - 節(jié)省更多內(nèi)存
瀏覽器程序中相同的功能方法,正在將瀏覽器的每個(gè)部分作為一項(xiàng)服務(wù)運(yùn)行,可以輕松拆分為不同進(jìn)程或聚合成一個(gè)進(jìn)程。 當(dāng)Chrome在強(qiáng)大的硬件上運(yùn)行時(shí),它可能會(huì)將每個(gè)服務(wù)拆分為不同的流程,從而提供更高的穩(wěn)定性,但如果它位于資源約束設(shè)備上,Chrome會(huì)將服務(wù)整合到一個(gè)流程中,從而節(jié)省內(nèi)存占用。
Android的平臺(tái)上已經(jīng)使用了類似的方法來(lái)整合流程以減少內(nèi)存使用。
圖片引自Mariko Kosaka的《Inside look at modern web browser》
7.給Iframe分配單獨(dú)渲染進(jìn)程 - 站點(diǎn)隔離
站點(diǎn)隔離:因不同站點(diǎn)之間共享內(nèi)存空間會(huì)存在同源策略繞過(guò)(Meltdown and Spectre)安全問題:https://blog.csdn.net/wlmnzf/article/details/79319509%22%20/t%20%22_blank。因此為每個(gè)跨網(wǎng)站iframe運(yùn)行單獨(dú)的渲染器進(jìn)程。
站點(diǎn)隔離難點(diǎn):從根本上改變iframe的通信方式,包括ctrl+F查找、打開devtools等需在不同渲染器進(jìn)程訪問?!局卮蟀姹尽?。
圖片引自Mariko Kosaka的《Inside look at modern web browser》
三、頁(yè)面導(dǎo)航過(guò)程
1. 瀏覽器進(jìn)程運(yùn)行
多進(jìn)程架構(gòu)啟動(dòng)多個(gè)進(jìn)程處理不同的任務(wù)。選項(xiàng)卡外部的所有內(nèi)容都由瀏覽器進(jìn)程處理(包含UI線程、網(wǎng)絡(luò)線程、存儲(chǔ)線程)。在地址欄輸入url時(shí),由瀏覽器進(jìn)程的UI線程處理。
圖片引自Mariko Kosaka的《Inside look at modern web browser》
2. 處理輸入
當(dāng)用戶開始輸入地址欄時(shí),UI線程需判斷是搜索查詢還是URL。
查詢:發(fā)送到搜索引擎
URL:請(qǐng)求URL的網(wǎng)站
3.開始導(dǎo)航
用戶點(diǎn)擊進(jìn)入時(shí):
有注冊(cè)設(shè)置Service Worker從緩存加載頁(yè)面,渲染進(jìn)程中運(yùn)行JavaScript代碼,從緩存加載頁(yè)面,無(wú)需請(qǐng)求網(wǎng)絡(luò)
未設(shè)置Service Worker時(shí):
1) UI線程啟動(dòng)網(wǎng)絡(luò)調(diào)用以獲取站點(diǎn)內(nèi)容,選項(xiàng)卡加載轉(zhuǎn)圈
2) 網(wǎng)絡(luò)線程通過(guò)DNS查找域名對(duì)應(yīng)IP及建立http連接
3) 網(wǎng)絡(luò)線程接收處理301重定向頭。網(wǎng)絡(luò)線程與請(qǐng)求重定向的UI線程通信,啟動(dòng)另一個(gè)URL請(qǐng)求
Service Worker
Service Worker注冊(cè)后,保留其范圍為參考。當(dāng)導(dǎo)航時(shí),網(wǎng)絡(luò)線程根據(jù)注冊(cè)的范圍檢查域名,若url已注冊(cè)Service Worker,UI線程找到渲染進(jìn)程執(zhí)行ServiceWorker代碼,從緩存加載數(shù)據(jù)或從網(wǎng)絡(luò)加載新資源。生命周期見:https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle
導(dǎo)航預(yù)加載
如果ServiceWorker最終決定從網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù),瀏覽器進(jìn)程與渲染進(jìn)程間的往返可能導(dǎo)致延時(shí),通過(guò)與ServiceWorker啟動(dòng)并行加載資源加速來(lái)減少延時(shí),允許標(biāo)記這些請(qǐng)求,允許服務(wù)器決定為這些請(qǐng)求發(fā)送不同的內(nèi)容。
圖片引自上面ServiceWorker的生命周期
4. 讀取響應(yīng)結(jié)果
4.1 確定文件MIME類型
網(wǎng)絡(luò)線程查看流的前幾個(gè)字節(jié),響應(yīng)頭中Content-Type頭確定MIME數(shù)據(jù)類型。因此數(shù)據(jù)可能丟失,因此用MIME嗅探方式來(lái)查看資源。https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types
4.2 處理不同MIME文件
響應(yīng)文件是HTML,則將數(shù)據(jù)傳遞給渲染器進(jìn)程。如果為.zip或其他文件則將數(shù)據(jù)傳遞給下載管理器。
4.3 安全檢查
惡意名單檢查:如果域和響應(yīng)數(shù)據(jù)在惡意站點(diǎn)名單中,則網(wǎng)絡(luò)線程發(fā)出和顯示警告頁(yè)面。
跨域讀取檢查:CrossOriginReadBlock檢查,敏感的跨站點(diǎn)數(shù)據(jù)不進(jìn)入渲染器進(jìn)程
5. 查找渲染進(jìn)程
所有檢查完成后,網(wǎng)絡(luò)線程告知UI線程數(shù)據(jù)已準(zhǔn)備就緒,UI線程找到渲染進(jìn)程以繼續(xù)渲染網(wǎng)頁(yè)。 由于網(wǎng)絡(luò)請(qǐng)求可能需要幾百毫秒才能得到響應(yīng),為加速此過(guò)程,在開始導(dǎo)航網(wǎng)絡(luò)線程發(fā)送url請(qǐng)求時(shí),已經(jīng)主動(dòng)進(jìn)行查找、啟動(dòng)渲染進(jìn)程,數(shù)據(jù)接收完成后,渲染進(jìn)程已備用。
6. 提交導(dǎo)航
現(xiàn)在數(shù)據(jù)和渲染器進(jìn)程已準(zhǔn)備就緒,IPC將從瀏覽器進(jìn)程發(fā)送到渲染進(jìn)程以提交導(dǎo)航。渲染進(jìn)程確認(rèn)提交完成,導(dǎo)航完成。文檔加載開始。 1、UI更新:地址欄更新、安全指示器、站點(diǎn)設(shè)置UI會(huì)反映新頁(yè)面站點(diǎn)信息 2、選項(xiàng)卡的會(huì)話歷史記錄更新(前進(jìn)/后退),為便于關(guān)閉瀏覽器后恢復(fù),歷史記錄到磁盤
7. 初始化 load complete
提交導(dǎo)航后,渲染器進(jìn)程將繼續(xù)加載資源并呈現(xiàn)頁(yè)面,一旦渲染器進(jìn)程“完成”(onload事件在所有幀上觸發(fā)執(zhí)行完成后)渲染,它就會(huì)將IPC發(fā)送回瀏覽器進(jìn)程。 UI線程停止選項(xiàng)卡的加載轉(zhuǎn)圈。
8.導(dǎo)航到其他站點(diǎn)
導(dǎo)航完成后,再次將不同的URL放到地址欄導(dǎo)航,瀏覽器會(huì)檢查當(dāng)前渲染網(wǎng)站的beforeunload事件。如有設(shè)置導(dǎo)航或關(guān)閉選項(xiàng)卡時(shí)發(fā)出警報(bào)“離開這個(gè)網(wǎng)站嗎?” 包含JavaScript代碼的選項(xiàng)卡內(nèi)的所有內(nèi)容都由渲染進(jìn)程處理。
渲染進(jìn)程導(dǎo)航操作 單擊鏈接或客戶端JavaScript已運(yùn)行window.location = “https://newsite.com“ ,過(guò)程與流程器進(jìn)程啟動(dòng)導(dǎo)航過(guò)程相同,不同點(diǎn)在于導(dǎo)航請(qǐng)求是從渲染進(jìn)程啟動(dòng)到瀏覽器進(jìn)程。
頁(yè)面生命周期:https://developers.google.com/web/updates/2018/07/page-lifecycle-api#overview_of_page_lifecycle_states_and_events
圖片引自上面的頁(yè)面生命周期
四、頁(yè)面渲染
1. 渲染進(jìn)程處理頁(yè)面內(nèi)容
渲染進(jìn)程負(fù)責(zé)選項(xiàng)卡內(nèi)發(fā)生的所有事情。在渲染器進(jìn)程中
主線程:處理您發(fā)送給用戶的大部分代碼。
工作線程:處理WebWorker或ServiceWorker
排版線程:Compositor
柵格線程
圖片引自Mariko Kosaka的《Inside look at modern web browser》
2. 解析
2.1 構(gòu)建DOM
當(dāng)渲染進(jìn)程接收提交的導(dǎo)航消息和HTML數(shù)據(jù),主線程開始解析文本串(HTML),使之成為一個(gè)DOM。解析中遇到html能優(yōu)雅容錯(cuò)。
DOM:瀏覽器頁(yè)面內(nèi)部表示,提供給開發(fā)人員通過(guò)JS與DOM交互的數(shù)據(jù)結(jié)構(gòu)和API。
圖片引自Mariko Kosaka的《Inside look at modern web browser》
2.2 子資源加載
網(wǎng)站通常使用圖像,CSS和JavaScript等外部資源,需要從網(wǎng)絡(luò)或緩存加載。在解析構(gòu)建DOM時(shí),主線程可以逐個(gè)請(qǐng)求它們。為了加快速度“預(yù)加載掃描器”同時(shí)運(yùn)行。
2.3 JavaScript阻塞解析
當(dāng)遇到