解釋器
用于解析和執(zhí)行 代碼,執(zhí)行結(jié)果將傳遞給渲染引擎來展示。
用戶界面后端
用于繪制基本的窗口小部件,比如組合框和窗口。其公開了與平臺(tái)無關(guān)的通用接口,而在底層使用操作系統(tǒng)的用戶界面方法。
數(shù)據(jù)存儲(chǔ)
這是持久層,瀏覽器需要在硬盤上保存各種數(shù)據(jù),例如 。新的 HTML 規(guī)范 (HTML5) 定義了“網(wǎng)絡(luò)數(shù)據(jù)庫”,這是一個(gè)完整而輕便的瀏覽器內(nèi)數(shù)據(jù)庫。
求同存異的瀏覽器架構(gòu)
下面列出了部分瀏覽器的架構(gòu)圖,也許有些架構(gòu)已經(jīng)改變,有興趣可以簡(jiǎn)單參考看看,除了IE之外,大體上各瀏覽器的整體架構(gòu)都是類似的。
架構(gòu):
ic
架構(gòu):
lla
架構(gòu):
me
架構(gòu):
ri
IE架構(gòu):
IE架構(gòu)
03
瀏覽器基本原理
V8
V8一詞最早見于“V-8 ”,即V8發(fā)動(dòng)機(jī),一般使用在中高端車輛上。8個(gè)氣缸分成兩組,每組4個(gè),成V型排列。是高層次汽車運(yùn)動(dòng)中最常見的發(fā)動(dòng)機(jī)結(jié)構(gòu),尤其在美國,IRL,和都要求使用V8發(fā)動(dòng)機(jī)。
關(guān)于 V8,筆者曾有一篇筆記做了比較詳細(xì)的介紹,全文脈絡(luò)如下,感興趣可以參考閱讀[8]。
-V8
V8是依托發(fā)展起來的,后面確不局限于瀏覽器內(nèi)核。發(fā)展至今V8應(yīng)用于很多場(chǎng)景,例如流行的,weex,快應(yīng)用,早期的RN。V8曾經(jīng)歷過一次比較大的架構(gòu)調(diào)整,主要變化在于“從字節(jié)碼的放棄到真香”。
V8 的早期架構(gòu)
V8引擎誕生的使命就是要在速度和內(nèi)存回收上進(jìn)行革命。的架構(gòu)是采用生成字節(jié)碼的方式,然后執(zhí)行字節(jié)碼。覺得這套架構(gòu)不行,生成字節(jié)碼會(huì)浪費(fèi)時(shí)間,不如直接生成機(jī)器碼快。所以V8在前期的架構(gòu)設(shè)計(jì)上是非常激進(jìn)的,采用了直接編譯成機(jī)器碼的方式。后期的實(shí)踐證明的這套架構(gòu)速度是有改善,但是同時(shí)也造成了「內(nèi)存消耗問題」。
V8-2010
早期的V8有Full-和兩個(gè)編譯器。V8 首先用 Full-把所有的代碼都編譯一次,生成對(duì)應(yīng)的機(jī)器碼。JS在執(zhí)行的過程中,V8內(nèi)置的篩選出熱點(diǎn)函數(shù)并且記錄參數(shù)的反饋類型,然后交給 來進(jìn)行優(yōu)化。所以Full-本質(zhì)上是生成的是未優(yōu)化的機(jī)器碼,而生成的是優(yōu)化過的機(jī)器碼。
隨著網(wǎng)頁的復(fù)雜化,V8也漸漸的暴露出了自己架構(gòu)上的缺陷:
V8 的現(xiàn)有架構(gòu)
為了解決上述缺點(diǎn),V8借鑒的架構(gòu),生成字節(jié)碼。V8采用生成字節(jié)碼的方式后,整體流程如下圖:
V8-2017
現(xiàn)在的 V8 是一個(gè)非常復(fù)雜的項(xiàng)目,有超過 100 萬行 C++代碼。它由許多子模塊構(gòu)成,其中這 4 個(gè)模塊是最重要的:
確切的說,在“”將 源碼轉(zhuǎn)換為 AST前,還有一個(gè)叫”“的過程,具體流程如下:
采用新的+架構(gòu)后,比Full-+架構(gòu)內(nèi)存降低一半多,且70%左右的網(wǎng)頁速度得到了提升。
在運(yùn)行 C、C++以及 Java 等程序之前,需要進(jìn)行編譯,不能直接執(zhí)行源碼;但對(duì)于 來說,我們可以直接執(zhí)行源碼(比如:node test.js),它是在運(yùn)行的時(shí)候先編譯再執(zhí)行,這種方式被稱為「即時(shí)編譯(Just-in-time )」,簡(jiǎn)稱為 JIT。因此,V8 也屬于 「JIT 編譯器」。
V8未誕生之前,早期主流的引擎是引擎。(以下簡(jiǎn)稱)主要服務(wù)于瀏覽器內(nèi)核,他們都是由蘋果公司開發(fā)并開源出來。是默認(rèn)內(nèi)嵌的JS引擎,之所以說是默認(rèn)內(nèi)嵌,是因?yàn)楹芏嗷诜种ч_發(fā)的瀏覽器引擎都開發(fā)了自家的JS引擎,其中最出名的就是前文提到的的V8。這些「JS引擎的使命都是解釋執(zhí)行JS腳本」。而在渲染流程上,JS和DOM樹之間存在著互相關(guān)聯(lián),這是因?yàn)闉g覽器中的JS腳本最主要的功能就是操作DOM樹,并與之交互。我們可以通過下圖看下它的工作流程:
主要模塊:「Lexer 詞法分析器,將腳本源碼分解成一系列的Token; 語法分析器,處理Token并生成相應(yīng)的語法樹;LLInt 低級(jí)解釋器,執(zhí)行生成的二進(jìn)制代碼; JIT 基線JIT(just in time 實(shí)時(shí)編譯);DFG 低延遲優(yōu)化的JIT;FTL 高通量?jī)?yōu)化的JIT」。
可以看到,相比靜態(tài)編譯語言生成語法樹之后,還需要進(jìn)行鏈接,裝載生成可執(zhí)行文件等操作,解釋型語言在流程上要簡(jiǎn)化很多。這張流程圖右邊畫框的部分就是的組成部分:Lexer(詞法分析)、(語法分析)、LLInt以及JIT(解釋執(zhí)行)的部分(之所以JIT的部分是用橙色標(biāo)注,是因?yàn)椴⒉皇撬械闹卸加蠮IT部分)。
PS:嚴(yán)格的講,語言本身并不存在編譯型或者是解釋型,因?yàn)檎Z言只是一些抽象的定義與約束,并不要求具體的實(shí)現(xiàn),執(zhí)行方式。這里講JS是一門“解釋型語言”只是JS一般是被JS引擎動(dòng)態(tài)解釋執(zhí)行,而并不是語言本身的屬性。
如果對(duì)有更多興趣,關(guān)于的更多細(xì)節(jié),建議延伸閱讀以下幾篇博文:
瀏覽器與
這一小結(jié),還是以 V8為例,簡(jiǎn)單闡述瀏覽器與的關(guān)系。
在 「V8 出現(xiàn)之前,所有的 虛擬機(jī)所采用的都是解釋執(zhí)行的方式,這是 執(zhí)行速度過慢的一個(gè)主要原因」。而 V8 率先引入了「即時(shí)編譯(JIT)**的**雙輪驅(qū)動(dòng)」的設(shè)計(jì)(混合使用編譯器和解釋器的技術(shù)),這是一種權(quán)衡策略,「混合編譯執(zhí)行和解釋執(zhí)行這兩種手段」,給 的執(zhí)行速度帶來了極大的提升。V8 出現(xiàn)之后,各大廠商也都在自己的 虛擬機(jī)中引入了 JIT 機(jī)制,所以目前市面上 虛擬機(jī)都有著類似的架構(gòu)。另外,「V8 也是早于其他虛擬機(jī)引入了惰性編譯、內(nèi)聯(lián)緩存、隱藏類等機(jī)制,進(jìn)一步優(yōu)化了 代碼的編譯執(zhí)行效率」。
V8 執(zhí)行一段 的流程
V8 執(zhí)行一段 的流程如下圖所示:
V8執(zhí)行一段流程圖
結(jié)合上文介紹的 V8 架構(gòu),聚焦到上,瀏覽器拿到源碼,, 以及 可以將 JS 源碼編譯為匯編代碼,其流程圖如下:
V8流程
簡(jiǎn)單地說, 將 JS 源碼轉(zhuǎn)換為 AST,然后 將 AST 轉(zhuǎn)換為 ,最后 將 轉(zhuǎn)換為經(jīng)過優(yōu)化的 Code(實(shí)際上是匯編代碼)。
圖片中的紅色虛線是逆向的,也就是說 Code 會(huì)被還原為 ,這個(gè)過程叫做 「」。這是因?yàn)? 收集的信息可能是錯(cuò)誤的,比如 add 函數(shù)的參數(shù)之前是整數(shù),后來又變成了字符串。生成的 Code 已經(jīng)假定 add 函數(shù)的參數(shù)是整數(shù),那當(dāng)然是錯(cuò)誤的,于是需要進(jìn)行 。
function add(x, y) {
return x + y;
}
add(1, 2);
add('1', '2');
「V8 本質(zhì)上是一個(gè)虛擬機(jī)」,因?yàn)橛?jì)算機(jī)只能識(shí)別二進(jìn)制指令,所以要讓計(jì)算機(jī)執(zhí)行一段高級(jí)語言通常有兩種手段:
簡(jiǎn)單總結(jié)如下,「V8 執(zhí)行一段 代碼所經(jīng)歷的主要流程」包括:
V8 的事件機(jī)制
關(guān)于異步編程和消息隊(duì)列,UI 線程提供一個(gè)消息隊(duì)列,并將待執(zhí)行的事件添加到消息隊(duì)列中,然后 UI 線程會(huì)不斷循環(huán)地從消息隊(duì)列中取出事件、執(zhí)行事件,通用 UI 線程宏觀架構(gòu)如下圖所示:
v8-ui
04
瀏覽器的不同形態(tài)
「 是一種嵌入式瀏覽器,原生應(yīng)用可以用它來展示網(wǎng)絡(luò)內(nèi)容」。 只是一個(gè)「可視化的」組件/控件/微件等。這樣我們可以用它來作為我們?cè)?app 的視覺部分。當(dāng)你使用原生應(yīng)用時(shí), 可能只是被隱藏在普通的原生 UI 元素中,你甚至用不到注意到它。
如果你把瀏覽器想象成兩部分,一部分是 UI(地址欄,導(dǎo)航欄按鈕等),其它部分是把標(biāo)記跟代碼轉(zhuǎn)換成我們可見和可交互視圖的引擎。「 就是瀏覽器引擎部分」,你可以像插入 一樣將 插入到你的原生應(yīng)用中瀏覽器不支持flash什么意思,并且編程化的告訴它將會(huì)加載什么網(wǎng)頁內(nèi)容。
運(yùn)行在你的 中的 有能力調(diào)用原生的系統(tǒng) API。這意味著你不必受到 Web 代碼通常必須遵守的傳統(tǒng)瀏覽器安全沙箱的限制。下圖解釋了使用這種技術(shù)后的架構(gòu)差異:
and
默認(rèn)情況下,在 或 Web 瀏覽器中運(yùn)行的任何 Web 代碼都與應(yīng)用的其余部分保持隔離。這樣做是出于安全原因,主要是為降低惡意的 代碼對(duì)系統(tǒng)造成的傷害。對(duì)于任意 Web 內(nèi)容,這種安全級(jí)別很有意義,因?yàn)槟阌肋h(yuǎn)不能完全信任加載的 Web 內(nèi)容。但 的情況并非如此,對(duì)于 方案,開發(fā)人員通常可以完全控制加載的內(nèi)容。惡意代碼進(jìn)入并在設(shè)備上造成混亂的可能性非常低。
「這就是為什么對(duì)于 ,開發(fā)人員可以使用各種受支持的方式來覆蓋默認(rèn)的安全行為,并讓 Web 代碼和原生應(yīng)用代碼相互通信。這種溝通通常稱為 」。你可以在上文的圖片中看到 可視化為 和 的一部分。
非常好,雖然它看起來像是完全特殊和獨(dú)特的,但請(qǐng)記住,它們只不過是一個(gè)在應(yīng)用中設(shè)置好位置和大小的、沒有任何花哨 UI 的瀏覽器,這就是它的精髓。大多數(shù)情況下,除非您調(diào)用原生 API,否則您不必在 中專門測(cè)試您的 Web 應(yīng)用程序。此外,您在 中看到的內(nèi)容與您在瀏覽器中看到的內(nèi)容相同,尤其是使用同一渲染引擎時(shí):
的應(yīng)用:
如果你對(duì) 感興趣,可通過以下幾篇文章繼續(xù)了解:
「無頭瀏覽器」是一種未配置圖形用戶界面 (GUI) 的 Web 瀏覽器,通常通過命令行或網(wǎng)絡(luò)通信來執(zhí)行。它主要由軟件測(cè)試工程師使用,沒有 GUI 的瀏覽器執(zhí)行速度更快,因?yàn)樗鼈儾槐乩L制視覺內(nèi)容。無頭瀏覽器的最大好處之一是它們能夠在沒有 GUI 支持的服務(wù)器上運(yùn)行。
瀏覽器對(duì)于測(cè)試網(wǎng)頁特別有用,因?yàn)樗鼈兡軌蛳駷g覽器一樣呈現(xiàn)和理解超文本標(biāo)記語言,包括頁面布局、顏色、字體選擇以及和AJAX的執(zhí)行等樣式元素,這些元素在使用其他測(cè)試方法時(shí)通常是不可用的。
e
瀏覽器有兩個(gè)主要可交付成果:
eteer
是一個(gè) Node 庫,他提供了一組用來操縱 的 API, 通俗來說就是一個(gè) 瀏覽器 (當(dāng)然你也可以配置成有 UI 的,默認(rèn)是沒有的)。既然是瀏覽器,那么我們手工可以在瀏覽器上做的事情 都能勝任, 另外, 翻譯成中文是”木偶”意思,所以聽名字就知道,操縱起來很方便,你可以很方便的操縱她去實(shí)現(xiàn):
1) 生成網(wǎng)頁截圖或者 PDF 2) 高級(jí)爬蟲,可以爬取大量異步渲染內(nèi)容的網(wǎng)頁 3) 實(shí)現(xiàn) UI 自動(dòng)化測(cè)試,模擬鍵盤輸入、表單自動(dòng)提交、點(diǎn)擊、登錄網(wǎng)頁等 4) 捕獲站點(diǎn)的時(shí)間線,以便追蹤你的網(wǎng)站,幫助分析網(wǎng)站性能問題 5) 模擬不同的設(shè)備 6) ...
跟 以及 最大的 的不同就是它是站在用戶瀏覽的角度,而 和 最初設(shè)計(jì)就是用來做自動(dòng)化測(cè)試的,所以它是站在機(jī)器瀏覽的角度來設(shè)計(jì)的,所以它們 使用的是不同的設(shè)計(jì)哲學(xué)。
(原名為Atom Shell)是 開發(fā)的一個(gè)開源框架。它通過使用 Node.js(作為后端)和 的渲染引擎(作為前端)完成跨平臺(tái)的桌面 GUI 應(yīng)用程序的開發(fā)。現(xiàn)已被多個(gè)開源 Web 應(yīng)用程序用于前端與后端的開發(fā),著名項(xiàng)目包括 的 Atom 和微軟的 Code。
由多個(gè) 和一個(gè) Main 進(jìn)程組成。Main 啟動(dòng) ,它們之間的通信是通過IPC [Inter ],如下圖所示。
e
我們常用的IDE 就是基于 (原來叫 Atom Shell) 進(jìn)行開發(fā)的。如下圖所示,(點(diǎn)擊 幫助【Help】 下的 切換開發(fā)人員工具即可打開以下面板)。
VS Code 的其他的主要組件有:
延伸閱讀: | Build cross- apps with , HTML, and CSS[27]
瀏覽器代碼兼容性測(cè)試
參考資料
本文首發(fā)于個(gè)人博客[44]瀏覽器不支持flash什么意思,歡迎指正和star[45]。
參考資料
[1]瀏覽器市場(chǎng)份額: %3A%2F%%%
[2]全球?yàn)g覽器市場(chǎng)份額: %3A%2F%%2F
[3]: %3A%2F%2F%.php
[] 為什么多進(jìn)程而不是多線程?: %3A%2F%2F%%
[5]經(jīng)典面試題:從 URL 輸入到頁面展現(xiàn)到底發(fā)生什么?: %3A%2F%%2Fp%
[6]在瀏覽器輸入 URL 回車之后發(fā)生了什么(超詳細(xì)版): %3A%2F%%2Fp%
[7]萬字詳文:深入理解瀏覽器原理: %3A%2F%%2Fp%
[8]參考閱讀: %3A%2F%%2Fa%
[9]: %3A%2F%2Fv8.dev%%
[10]: %3A%2F%2Fv8.dev%%
[11]: %3A%2F%2Fv8.dev%%
[12]: %3A%2F%2Fv8.dev%%-talk
[13]深入理解: %3A%2F%%%2F08%2F23%--of-.html
[14]深入剖析 : %3A%2F%..io%%2F04%2F21%--%2F
[15] 全面解析:
[16]深入淺出 : %3A%2F%2F%2Fp%
[17]7.5.1 (網(wǎng)頁視圖)基本用法: %3A%2F%2F%%--.html
[18]:這是一份全面 & 詳細(xì)的使用攻略: %3A%2F%2F%2Fp%%2F
[19] : %3A%2F%2F%%2Fp%.html
[20]: %3A%2F%%%%2F
[21] 入門教程: %3A%2F%2F%%.html
[22]結(jié)合項(xiàng)目來談?wù)?: %3A%2F%%2Fp%
[23] : %3A%2F%%%-
[24] : %3A%2F%%%--
[25]Debug : %3A%2F%%%--
[26]Xterm.js: %3A%2F%%2F
[27] | Build cross- apps with , HTML, and CSS: %3A%2F%..io%%%%.html
[28]: %3A%2F%2F%2F
[29]: %3A%2F%2F%
[30]: %3A%2F%%2F
[31]瀏覽器簡(jiǎn)史: %3A%2F%2F%%-ie%2F
[32]Web 瀏覽器相關(guān)的一些概念: %3A%2F%%%-11-24---to-web-
[33]瀏覽器的工作原理:新式網(wǎng)絡(luò)瀏覽器幕后揭秘: %3A%2F%2F%2Fzh%%%%2F
[34]從瀏覽器多進(jìn)程到 JS 單線程,JS 運(yùn)行機(jī)制最全面的一次梳理: %3A%2F%%2Fa%
[35] look at web : %3A%2F%%2Fweb%%%2F09%--part1
[36] look at web : %3A%2F%%2Fweb%%%2F09%--part1
[37]瀏覽器是如何工作的: V8 讓你更懂 : %3A%2F%%2Fa%
[38]深入理解: %3A%2F%%%2F08%2F23%--of-.html
[39]The Story of the Web: A Of : %3A%2F%2F%2Fthe-story-of-the-web-a--of--
[40]PPT - : %3A%2F%%2Fsb-files%.pdf
[41] 引擎 V8 執(zhí)行流程概述: %3A%2F%%%-%2F
[42] : %3A%2F%2F%%.htm
[43] Up Close: What is a ?: %3A%2F%%%2F05%-up-close-what-is-a--%2F
[44]個(gè)人博客: %3A%2F%-hcj..io%%2F07%2F11%2Fweb-%2F
[45]指正和star: %3A%2F%%-hcj%-hcj..io
安排上了!這次是真人版動(dòng)畫演示快速排序