深入理解浏览器原理和架构|硬核
本文用47張圖帶你了解「瀏覽器的發展史」、「瀏覽器的架構」、「瀏覽器的基本原理」以及?「瀏覽器的其它小知識」
???? 正文開始
瀏覽器的主要功能就是向服務器發出請求,在瀏覽器窗口中展示HTML文檔、PDF、圖片、視頻等網絡內容。這些網絡資源的位置由用戶使用 URI(統一資源標示符)來指定指定。
或許在大多數人眼中,瀏覽器是這樣的:
大多數人眼中的瀏覽器「一個展示前端,一個未知的中間層連接著網絡世界」;甚至,網絡世界也可以省略:一臺顯示器,一個神秘的幕后黑盒。
如果你是一個前端開發者,甚至每天瀏覽器陪伴你度過的時光比女朋友陪伴你的都要久,想想那每一個令人“不是那么期待”的早晨,每一個爭分奪秒完成任務的黃昏,只有瀏覽器和編輯器一直是你忠實的伙伴。而「就連你一直離不開的VS Code編輯器,甚至也與瀏覽器有著莫大的淵源」。
屏幕前的朋友,你熟悉自己身邊的那些人嗎,熟悉那些與你朝夕相伴的朋友嗎?也許熟悉,也許不,那么,你是否愿意花些時間來熟悉一下這個在大量時間里與你有著莫大交集的瀏覽器的內心世界呢?
今天,我們就來一探究竟,走進這個我們與網絡連接最緊密的中間地帶。全文行文結構大概如下:
目錄結構瀏覽器發展簡史
瀏覽器的誕生與發展
也許你知道,第一款瀏覽器 —— WorldWideWeb,誕生于1990年。但是現代瀏覽器的雛形卻孕育于 1980s年代。
一位名叫蒂姆·伯納斯-李的英國科學家在 1980 年代初期創建了一個名為 Inquire 的計算機程序,當時他在總部位于瑞士的歐洲核研究組織(CERN,以其法文字母表示)工作。該計劃旨在「使在 CERN 工作的許多不同個人更容易共享信息」。
1990年,第一款瀏覽器問世于Tim Berners-Lee 在 CERN 工作期間。您可能想知道 Web 瀏覽器到底是什么,簡而言之,它是一個計算機程序,其目的是顯示和檢索數據。使用分配給存儲在網絡服務器上的每個數據集(網頁)的 URL,它可以做到這一點。所以這意味著「當您在瀏覽器中輸入內容時,您實際上是在輸入地址」,瀏覽器將使用該地址來獲取您想要查看的信息。「瀏覽器的另一個關鍵功能是以易于理解的方式向您解釋和呈現計算機代碼」。
下圖簡單羅列了截止2020年瀏覽器的發展簡史:
Timeline_of_the_Web_Browsers早期比較有名、有意義的瀏覽器主要包括Erwise、ViolaWWW、Mosaic、Netscape Navigator:
The-Early-Browsers1990年瀏覽器誕生之后的故事,想必您已經早有耳聞:
「NCSA Mosaic」,或簡稱 Mosaic,是互聯網歷史上「第一個獲普遍使用和能夠顯示圖片的網頁瀏覽器」。它由伊利諾伊大學厄巴納-香檳分校的NCSA組織在1993年發表,并于1997年1月7日正式終止開發和支持,這款瀏覽器在當時大受歡迎。Mosaic的出現,算是點燃了后期互聯網熱潮的火種之一。后來 Netscape Navigator 瀏覽器的開發,聘用了許多原有的 Mosaic 瀏覽器工程師,但是沒有采用 Mosaic 網頁瀏覽器的任何代碼。而傳承網景瀏覽器代碼的后裔為Firefox瀏覽器。
Marc Andreesen 與同事 Jim Clark 于 1994 年成立了一家公司,當時 Mosaic 還是最流行的瀏覽器,它們計劃打造出一個比 Mosaic 更好的瀏覽器,占領市場,讓他們變得富有,并改變歷史。他們的第一個瀏覽器被稱為 Mosaic Netscape 0.9,不久更名 Netscape。得益于 JavaScript(JavaScript誕生于1995年,它是Netscape的Brendan Eich 僅花費十天設計實現的。) 和“partial-screen loading”(即使頁面未完全加載,用戶也可以開始閱讀頁面上的詳細信息,這一個新概念極大地豐富了在線體驗)等功能,它很快成為市場領導者,占據了瀏覽器市場上一半的份額,最瘋狂的時候,網景瀏覽器的市場份額接近百分之九十。
1995年8月9日,網景公開募股,最初的價格是14美元一股,但后來陰差陽錯,改為28美元一股發行,當天收盤時,網景的股票成了75美元一股,網景成為了當時世界上市值最高的互聯網公司,Netscape 的 IPO 也助長了日益增長的網絡泡沫。
Netscape 最初的成功向那些在計算機和互聯網領域工作的人證明時代已經永遠改變了,這讓當時業內最強大的參與者感到震驚,一家名為 Microsoft 的西雅圖公司就是其中之一。計算機將通過瀏覽器運行,瀏覽器可以在任何機器上運行,從而使軟件行業民主化并降低其相當大的進入壁壘,這導致許多人猜測「操作系統的時代已經結束」。Netscape 對微軟來說是一個挑戰,微軟在 1990 年代后期創建了自己的瀏覽器 Internet Explorer,當時的IE和現在一樣,通常被視為劣質產品。由于「微軟已經建立了銷售其專有操作系統 Windows 的帝國」,因此將這種由 Netscape 等公司帶頭的發展視為一種威脅。微軟通過對其產品的大量投資,使其與 Netscape 一樣好,成功地迅速扭轉了瀏覽器行業的局面。Windows 計算機在發布時已經安裝了 Internet Explorer(Microsoft 的瀏覽器),這使其能夠在市場上占據一席之地并不斷發展壯大,最終在瀏覽器領域取得了勝利,這便是著名的「第一次瀏覽器大戰」。
市場份額的快速下滑導致 Netscape 被出售給了 AOL,2003年7月,網景解散,就在解散的當天,Mozilla基金會成立,2004年基于Mozilla源碼的Firefox首次登臺,拉開了第二次瀏覽器大戰的序幕。2008 年Netscape最終滅絕,「當年的瀏覽器帝國正式退出了歷史的舞臺」。
到 2003 年,微軟的 Internet Explorer 控制了 92% 以上的市場,完全扭轉了 1995 年的局面。然而,雖然微軟在不到十年的時間里成功地完全接管了瀏覽器市場,但很快就會出現其他競爭,再次重塑網絡瀏覽器的歷史。
微軟在 1990 年代后期崛起并讓 Netscape 等公司屈服之后,瀏覽器的歷史似乎已經走到了盡頭。然而,正如最初發布后的情況一樣,Internet Explorer 正在成為劣質產品。谷歌于 2008 年推出了其專有瀏覽器——Chrome。到 2012 年底,即推出僅四年后,谷歌 Chrome 瀏覽器憑借其易用性、跨平臺功能、速度以及與標簽和書簽相關的特殊功能,取代 Internet Explorer 成為最受歡迎的瀏覽器。
在 2000 年代初期,可能是在微軟將瀏覽器附加到其操作系統之后,Apple 發布了 Safari,一種專為 Mac 設計的瀏覽器,并成為目前市場上第二大瀏覽器。
Internet Explorer 的流行度在 2000 年代后期逐漸減少,主要是因為它變得緩慢和過時,而 Microsoft 發現自己現在似乎已經是在外面觀察瀏覽器世界。該公司不想繼續錯過,于是著手解決這個問題,但發現一個關鍵問題是“Internet Explorer”這個名字已經成為劣質瀏覽器的同義詞。因此,為了嘗試重新進入游戲,微軟不得不重新命名,是以,Edge 變誕生了。Edge是微軟瀏覽器的最新版本,它受到了很多好評,但對于 Microsoft 來說,Edge 的出現可能為時已晚。
「IE瀏覽器終成時代之淚,Microsoft Edge 成為Windows 11的默認瀏覽器」。這是Windows系統更新20年來,IE的首次缺席,也是最后一次。早在Win10更新時微軟就表示,將放棄更新IE轉向開發新的瀏覽器Microsoft Edge。如今是徹底要和桌面上的IE說再見了。—— IE 瀏覽器將從 Windows 11 中消失,它也將在 2022 年安息。
瀏覽器市場份額
截止2021年7月初,瀏覽器市場份額如下所示。
瀏覽器使用趨勢變化:
Web_Browser_Usage_Trends瀏覽器市場份額:
Web_Browser_Market_Share國內瀏覽器市場份額:
Web_Browser_Market_Share_CHN如果你對以上瀏覽器市場份額數據有興趣,可以通過以下鏈接進行查看:
國內瀏覽器市場份額
瀏覽器市場份額[1]
全球瀏覽器市場份額
全球瀏覽器市場份額[2]
w3counter[3]
瀏覽器架構
計算機的核心
三層計算機體系結構:底部是機器硬件,中間是操作系統,頂部是應用程序。
hw-os-app當你在電腦或手機上啟動應用時,是?「CPU 和 GPU 為應用供能」。通常情況下應用是通過操作系統提供的機制在 CPU 和 GPU 上運行。
CPU
中央處理器(Central Processing Unit),或簡稱為 CPU。CPU 可以看作是計算機的大腦。「一個 CPU 核心如圖中的辦公人員,可以逐一解決很多不同任務」。它可以在解決從數學到藝術一切任務的同時還知道如何響應客戶要求。過去 CPU 大多是單芯片的。隨著現代硬件發展,你經常會有不止一個內核,為你的手機和筆記本電腦提供更多的計算能力。
4 個 CPU 核心作為辦公人員,坐在辦公桌前處理各自的工作:
CPUGPU
圖形處理器(Graphics Processing Unit,簡稱為 GPU)是計算機的另一部件。與 CPU 不同,GPU 擅長同時處理跨內核的簡單任務。顧名思義,「它最初是為解決圖形而開發的」。這就是為什么在圖形環境中“使用 GPU” 或 “GPU 支持”都與快速渲染和順滑交互有關。近年來隨著 GPU 加速計算的普及,僅靠 GPU 一己之力也使得越來越多的計算成為可能。
下圖中,許多帶特定扳手的 GPU 內核意味著它們只能處理有限任務。
GPU進程與線程
進程可以被描述為是一個應用的執行程序。線程是位于進程內部并執行其進程程序的任意部分。
啟動應用時會創建一個進程。程序也許會創建一個或多個線程來幫助它工作。操作系統為進程提供了一個可以使用的“一塊”內存,所有應用程序狀態都保存在該私有內存空間中。關閉應用程序時,相應的進程也會消失,操作系統會釋放內存(下圖中,邊界框為進程,線程作為抽象魚在進程中游動)。
memory進程可以請求操作系統啟動另一個進程來執行不同的任務。此時,內存中的不同部分會分給新進程。如果兩個進程需要對話,他們可以通過**進程間通信(IPC)**來進行。許多應用都是這樣設計的,所以如果一個工作進程失去響應,該進程就可以在不停止應用程序不同部分的其他進程運行的情況下重新啟動。
workerprocess.gif瀏覽器的進程/線程架構模型
瀏覽器進程分類
關于如何「構建 web 瀏覽器并不存在標準規范」,一個瀏覽器的構建方法可能與另一個迥然不同。不同瀏覽器的進程/線程架構一般由下圖幾部分:
browser-archChrome多進程架構
而當下“瀏覽器世界的王者” Chrome 架構如下圖所示,渲染進程下顯示了多個層,表明 Chrome 為每個標簽頁運行多個渲染進程。
browser-arch-chrome上圖中,頂部是瀏覽器進程,它與處理應用其它模塊任務的進程進行協調。對于渲染進程來說,創建了多個渲染進程并分配給了每個標簽頁。Chrome 在可能的情況下會給每個標簽頁分配一個進程。而現在它試圖給每個站點分配一個進程,包括 iframe。
瀏覽器進程:控制應用中的 “Chrome” 部分,包括地址欄,書簽,回退與前進按鈕,以及處理 web 瀏覽器中網絡請求、文件訪問等不可見的特權部分;
渲染進程:控制標簽頁內網站展示;
插件進程:控制站點使用的任意插件,如 Flash;
GPU進程:處理獨立于其它進程的 GPU 任務。GPU 被分成不同進程,因為 GPU 處理來自多個不同應用的請求并繪制在相同表面。
可以簡單理解為不同進程對應瀏覽器 UI 的不同部分:
browserui「Chrome 更多的是把自己抽象為一個操作系統,網頁或擴展相當于一個個程序」,你甚至可以發現,Chrome 確實自帶了一個任務管理器,在任務管理器面板會列出當前正在運行的進程以及它們當前的 CPU/內存使用量情況等信息。
一般你可以通過兩種方法打開Chrome任務管理器:
通過在瀏覽器頂欄(標簽tab欄)右側右鍵,選擇任務管理器查看;
點擊 Chrome 瀏覽器右上角的“選項”菜單(一般是三個點的標識),選擇“更多工具”子菜單,點擊“任務管理器”,打開任務管理器窗口。
前文中提到了 Chrome 使用多個渲染進程,那他有什么優勢呢?
穩定性:最簡單的情況下,你可以想象每個標簽頁都有自己的渲染進程。假設你打開了三個標簽頁,每個標簽頁都擁有自己獨立的渲染進程。如果某個標簽頁失去響應,你可以關掉這個標簽頁,此時其它標簽頁依然運行著,可以正常使用。如果所有標簽頁都運行在同一進程上,那么當某個失去響應,所有標簽頁都會失去響應,顯然這樣的體驗會很糟糕。下面是多/單進程架構的對比動圖,供你參考。
安全性與沙箱化:把瀏覽器工作分成多個進程的另一好處是安全性與沙箱化。由于操作系統提供了限制進程權限的方法,瀏覽器就可以用沙箱保護某些特定功能的進程。例如,Chrome 瀏覽器可以限制處理用戶輸入(如渲染器)的進程的文件訪問的權限。
由于進程有自己的私有內存空間,所以它們通常包含公共基礎設施的拷貝(如Chrome V8引擎)。這意味著使用了更多的內存,如果它們是同一進程中的線程,就無法共享這些拷貝(同一個進程中的線程不共享堆棧,堆棧是保證線程獨立運行所必須的)。為了節省內存,Chrome 對可啟動的進程數量有所限制。具體限制數值依設備可提供的內存與 CPU 能力而定,但是「當 Chrome 運行時達到限制時,會開始在同一站點的不同標簽頁上運行同一進程」。
Chrome 正在經歷架構變革,它轉變為將瀏覽器程序的每一模塊作為一個服務來運行,從而可以輕松實現進程的拆解或聚合。具體表現是,當 Chrome 運行在「強力硬件」上時,它會將每個服務分解到不同進程中,從而「提升穩定性」,但是如果 Chrome 運行在資源有限的設備上時,它會將服務聚合到一個進程中從而「節省了內存占用」。在這一架構變革實現前,類似的整合進程以減少內存使用的方法已經在 Android 類平臺上使用。
servicfication.gifChrome 67 版本后,桌面版 Chrome 都默認開啟了「站點隔離」,每個標簽頁的 iframe 都有一個單獨的渲染進程。啟用站點隔離是多年來工程人員努力的結果。站點隔離并不只是分配不同的渲染進程這么簡單。它從根本上改變了 iframe 的通信方式。在一個頁面上打開開發者工具,讓 iframe 在不同的進程上運行,這意味著開發者工具必須在幕后工作,以使它看起來無縫。即使運行一個簡單的 Ctrl + F 來查找頁面中的一個單詞,也意味著在不同的渲染器進程中進行搜索。你可以看到為什么「瀏覽器工程師把發布站點隔離功能作為一個重要里程碑」!
isolation延伸閱讀:Chrome 為什么多進程而不是多線程?[4]
瀏覽器整體架構
如果您是一名前端工程師,那么,面試時你大概率會被問到過:從 URL 輸入到頁面展現到底發生了什么?,如果您對這一過程不太熟悉,建議看看下面兩篇文章,在此不過多贅述:
經典面試題:從 URL 輸入到頁面展現到底發生什么?[5]
在瀏覽器輸入 URL 回車之后發生了什么(超詳細版)[6]
瀏覽器的主要任務之一就是渲染展示頁面,不同的瀏覽器內核,渲染過程也不完全相同,但大致流程都差不多,下面這張圖片是火狐瀏覽器(Firefox,可以認為是Netscapede的涅槃重生)開發文檔中的一張圖片。
瀏覽器架構上面這張圖片大體揭示了瀏覽器的渲染展示流程,但是從瀏覽器的整體架構上來說,上面的圖片展示的也許只是瀏覽器體系中的冰山一角。
通常意義下,瀏覽器架構是如下圖這樣的:
瀏覽器架構用戶界面
包括地址欄、前進/后退按鈕、書簽菜單等。除了瀏覽器主窗口顯示的您請求的頁面外,其他顯示的各個部分都屬于用戶界面。
瀏覽器引擎
用戶界面和渲染引擎的橋梁,在用戶界面和渲染引擎之間傳送指令。瀏覽器引擎提供了開始加載URL資源 和一些其他高級操作方法,比如:重新加載、前進、后退動作,錯誤信息、加載進度等。
渲染引擎
負責顯示請求的內容。如果請求的內容是 HTML,它就負責解析 HTML 和 CSS 內容,并將解析后的內容顯示在屏幕上。
所謂瀏覽器內核就是指瀏覽器最重要或者說核心的部分"Rendering Engine",譯為"渲染引擎"。負責對網頁語法的解析,比如HTML、JavaScript,并渲染到網頁上。所以瀏覽器內核也就是瀏覽器所采用的渲染引擎,渲染引擎決定這瀏覽器如何顯示頁面的內容和頁面的格式信息。不同的瀏覽器內核對語法的解釋也不相同,因此同一網頁在不同內核的瀏覽器顯示的效果也會有差異(瀏覽器兼容)。這也就是網頁開發者在不需要同內核的瀏覽器中測試網頁顯示效果的原因。
RENDERING ENGINE延伸閱讀:曾紅極一時的紅芯瀏覽器,官網對其介紹是:擁有智能的認證引擎、渲染引擎、管控引擎,而且還有強大的“國密通訊協議”,支持統一管控、遠程控制。2018年8月15日,紅芯瀏覽器被爆出打開安裝目錄后出現大量和谷歌Chrome瀏覽器一致的同名文件,其安裝程序的文件屬性中也顯示了原始文件名chrome.exe,紅芯瀏覽器的官網已撤下了瀏覽器的下載鏈接。8月16日,紅芯聯合創始人高婧回應,紅芯瀏覽器“包含‘Chrome’在里面”,但并非抄襲,而是“站在巨人的肩膀上去做創新”。
hongxin言歸正傳,瀏覽器內核主要包括以下三個技術分支:排版渲染引擎、 JavaScript引擎,以及其他。
排版引擎:
KHTML:KHTML,是HTML網頁排版引擎之一,由KDE所開發。KHTML擁有速度快捷的優點,但對錯誤語法的容忍度則比Mozilla產品所使用的Gecko引擎小。蘋果電腦于2002年采納了KHTML,作為開發Safari瀏覽器之用,并發布所修改的最新及過去版本源代碼。「后來發表的開源WebCore及WebKit引擎,它們均是KHTML的衍生產品」。
WebCore:WebCore是「蘋果公司」開發的排版引擎,它是在另外一個排版引擎“KHTML”的基礎上而來的。使用WebCore的主要有Safari瀏覽器。
瀏覽器的內核引擎,基本上是四分天下:
Trident: IE 以Trident 作為內核引擎;
Gecko: Firefox 是基于 Gecko 開發;
WebKit: 誕生于1998年,并于2005年由Apple公司開源,Safari, Google Chrome,傲游3,獵豹瀏覽器,百度瀏覽器 opera瀏覽器 基于 Webkit 開發。
Presto: Opera的內核,但由于市場選擇問題,主要應用在手機平臺--Opera mini。(2013年2月Opera宣布轉向WebKit引擎,2013年4月Opera宣布放棄WEBKIT,跟隨GOOGLE的新開發的blink引擎。)
需要略作補充的是,我們經常還會聽到Chromium、Webkit2、Blink這些引擎。
Chromium:基于webkit,08年開始作為Chrome的引擎,Chromium瀏覽器是Chrome的實驗版,實驗新特性。可以簡單地理解為:Chromium為實驗版,具有眾多新特性;Chrome為穩定版。
圖片來源:萬字詳文:深入理解瀏覽器原理[7]
Webkit2:2010年隨OS X Lion一起面世。WebCore層面實現進程隔離與Google的沙箱設計存在沖突。
Blink:基于Webkit2分支,是WebKit中WebCore組件的一個分支,13年谷歌開始作為Chrome 28的引擎集成在Chromium瀏覽器里。Android的WebView同樣基于Webkit2,是現在對新特性支持度最好的內核。Opera(15及往后版本)和Yandex瀏覽器中也在使用。
移動端基本上全部是 Webkit 或 Blink 內核(除去 Android 上騰訊家的 X5),這兩個內核對新特性的支持度較高,所以新特性可以在移動端大展身手。
各內核關系圖:
KHTML下面我們以WebKit為列,進行簡單介紹,以便讓你對渲染引擎有一個更多的理解。WebKit由多個重要模塊組成,通過下圖我們可以對WebKit有個整體的了解:
WebKitWebKit就是一個「頁面渲染以及邏輯處理引擎」,前端工程師把HTML、JavaScript、CSS這“三駕馬車”作為輸入,經過WebKit的處理,就輸出成了我們能看到以及操作的Web頁面。從上圖我們可以看出來,WebKit由圖中框住的四個部分組成。而其中最主要的就是WebCore和JSCore(或者是其它JS引擎)。除此之外,WebKit Embedding API是負責瀏覽器UI與WebKit進行交互的部分,而WebKit Ports則是讓Webkit更加方便的移植到各個操作系統、平臺上,提供的一些調用Native Library的接口,比如在渲染層面,在iOS系統中,Safari是交給CoreGraphics處理,而在Android系統中,Webkit則是交給Skia。
WebKit的渲染流程:
WebKit-Rendering首先瀏覽器通過URL定位到了一堆由HTML、CSS、JS組成的資源文件,通過加載器把資源文件給WebCore。之后HTML Parser會把HTML解析成DOM樹,CSS Parser會把CSS解析成CSSOM樹。最后把這兩棵樹合并,生成最終需要的渲染樹,再經過布局,與具體WebKit Ports的渲染接口,把渲染樹渲染輸出到屏幕上,成為了最終呈現在用戶面前的Web頁面。
網絡
用于網絡調用,比如 HTTP 請求。其接口與平臺無關,并為所有平臺提供底層實現,負責網絡通信和安全。
JavaScript 解釋器
用于解析和執行 JavaScript 代碼,執行結果將傳遞給渲染引擎來展示。
用戶界面后端
用于繪制基本的窗口小部件,比如組合框和窗口。其公開了與平臺無關的通用接口,而在底層使用操作系統的用戶界面方法。
數據存儲
這是持久層,瀏覽器需要在硬盤上保存各種數據,例如 Cookie。新的 HTML 規范 (HTML5) 定義了“網絡數據庫”,這是一個完整而輕便的瀏覽器內數據庫。
求同存異的瀏覽器架構
下面列出了部分瀏覽器的架構圖,也許有些架構已經改變,有興趣可以簡單參考看看,除了IE之外,大體上各瀏覽器的整體架構都是類似的。
Mosaic架構:
Architecture_of_MosaicFirefox架構:
Architecture_of_MozillaChrome架構:
Architecture_of_ChromeSafari架構:
Architecture_of_SafariIE架構:
IE架構瀏覽器基本原理
Chrome V8
V8一詞最早見于“V-8 engine”,即V8發動機,一般使用在中高端車輛上。8個氣缸分成兩組,每組4個,成V型排列。是高層次汽車運動中最常見的發動機結構,尤其在美國,IRL,ChampCar和NASCAR都要求使用V8發動機。
關于Chrome V8,筆者曾有一篇筆記做了比較詳細的介紹,全文脈絡如下,感興趣可以參考閱讀[8]。
Chrome-V8V8是依托Chrome發展起來的,后面確不局限于瀏覽器內核。發展至今V8應用于很多場景,例如流行的nodejs,weex,快應用,早期的RN。V8曾經歷過一次比較大的架構調整,主要變化在于“從字節碼的放棄到真香”。
V8 的早期架構
V8引擎誕生的使命就是要在速度和內存回收上進行革命。JavaScriptCore的架構是采用生成字節碼的方式,然后執行字節碼。Google覺得JavaScriptCore這套架構不行,生成字節碼會浪費時間,不如直接生成機器碼快。所以V8在前期的架構設計上是非常激進的,采用了直接編譯成機器碼的方式。后期的實踐證明Google的這套架構速度是有改善,但是同時也造成了「內存消耗問題」。
V8-2010早期的V8有Full-Codegen和Crankshaft兩個編譯器。V8 首先用 Full-Codegen把所有的代碼都編譯一次,生成對應的機器碼。JS在執行的過程中,V8內置的Profiler篩選出熱點函數并且記錄參數的反饋類型,然后交給 Crankshaft 來進行優化。所以Full-Codegen本質上是生成的是未優化的機器碼,而Crankshaft生成的是優化過的機器碼。
隨著網頁的復雜化,V8也漸漸的暴露出了自己架構上的缺陷:
Full-Codegen 編譯直接生成機器碼,導致「內存占用大」;
Full-Codegen 編譯直接生成機器碼,導致「編譯時間長」,導致「啟動速度慢」;
Crankshaft 無法優化try,catch和finally等關鍵字劃分的代碼塊;
Crankshaft 新加語法支持,需要為此編寫適配不同的Cpu架構代碼。
V8 的現有架構
為了解決上述缺點,V8借鑒JavaScriptCore的架構,生成字節碼。V8采用生成字節碼的方式后,整體流程如下圖:
V8-2017現在的 V8 是一個非常復雜的項目,有超過 100 萬行 C++代碼。它由許多子模塊構成,其中這 4 個模塊是最重要的:
Parser[9]:負責將 JavaScript 源碼轉換為 Abstract Syntax Tree (AST)
確切的說,在“Parser”將 JavaScript 源碼轉換為 AST前,還有一個叫”Scanner“的過程,具體流程如下:
ScannerIgnition[10]:interpreter,即解釋器,負責將 AST 轉換為 Bytecode,解釋執行 Bytecode;同時收集 TurboFan 優化編譯所需的信息,比如函數參數的類型;解釋器執行時主要有四個模塊,內存中的字節碼、寄存器、棧、堆。Ignition的原始動機是減少移動設備上的內存消耗。在Ignition之前,V8的Full-codegen基線編譯器生成的代碼通常占據Chrome整體JavaScript堆的近三分之一。這為Web應用程序的實際數據留下了更少的空間。Ignition的字節碼可以直接用TurboFan生成優化的機器代碼,而不必像Crankshaft那樣從源代碼重新編譯。Ignition的字節碼在V8中提供了更清晰且更不容易出錯的基線執行模型,簡化了去優化機制,這是V8 自適應優化的關鍵特性。最后,由于生成字節碼比生成Full-codegen的基線編譯代碼更快,因此激活Ignition通常會改善腳本啟動時間,從而改善網頁加載。
TurboFan[11]:compiler,即優化編譯器,利用 Ignition 所收集的類型信息,將 Bytecode 轉換為優化的匯編代碼;TurboFan項目最初于2013年底啟動,旨在解決Crankshaft的缺點。Crankshaft只能優化JavaScript語言的子集。例如,它不是設計用于使用結構化異常處理優化JavaScript代碼,即由JavaScript的try,catch和finally關鍵字劃分的代碼塊。很難在Crankshaft中添加對新語言功能的支持,因為這些功能幾乎總是需要為九個支持的平臺編寫特定于體系結構的代碼。
Orinoco[12]:garbage collector,垃圾回收模塊,負責將程序不再需要的內存空間回收。
采用新的Ignition+TurboFan架構后,比Full-codegen+Crankshaft架構內存降低一半多,且70%左右的網頁速度得到了提升。
在運行 C、C++以及 Java 等程序之前,需要進行編譯,不能直接執行源碼;但對于 JavaScript 來說,我們可以直接執行源碼(比如:node test.js),它是在運行的時候先編譯再執行,這種方式被稱為「即時編譯(Just-in-time compilation)」,簡稱為 JIT。因此,V8 也屬于?「JIT 編譯器」。
JavaScriptCore
V8未誕生之前,早期主流的JavaScript引擎是JavaScriptCore引擎。JavaScriptCore(以下簡稱JSCore)主要服務于Webkit瀏覽器內核,他們都是由蘋果公司開發并開源出來。JSCore是WebKit默認內嵌的JS引擎,之所以說是默認內嵌,是因為很多基于WebKit分支開發的瀏覽器引擎都開發了自家的JS引擎,其中最出名的就是前文提到的Chrome的V8。這些「JS引擎的使命都是解釋執行JS腳本」。而在渲染流程上,JS和DOM樹之間存在著互相關聯,這是因為瀏覽器中的JS腳本最主要的功能就是操作DOM樹,并與之交互。我們可以通過下圖看下它的工作流程:
JavaScriptCoreJavaScriptCore主要模塊:「Lexer 詞法分析器,將腳本源碼分解成一系列的Token;Parser 語法分析器,處理Token并生成相應的語法樹;LLInt 低級解釋器,執行Parser生成的二進制代碼;Baseline JIT 基線JIT(just in time 實時編譯);DFG 低延遲優化的JIT;FTL 高通量優化的JIT」。
可以看到,相比靜態編譯語言生成語法樹之后,還需要進行鏈接,裝載生成可執行文件等操作,解釋型語言在流程上要簡化很多。這張流程圖右邊畫框的部分就是JSCore的組成部分:Lexer(詞法分析)、Parser(語法分析)、LLInt以及JIT(解釋執行)的部分(之所以JIT的部分是用橙色標注,是因為并不是所有的JSCore中都有JIT部分)。
「詞法分析」很好理解,就是「把一段我們寫的源代碼分解成Token序列的過程」,這一過程也叫「分詞」。在JSCore,詞法分析是由Lexer來完成(有的編譯器或者解釋器把分詞叫做Scanner,比如Chrome v8)。
跟人類語言一樣,我們講話的時候其實是按照約定俗成,交流習慣按照一定的語法講出一個又一個詞語。那類比到計算機語言,計算機要理解一門計算機語言,也要理解一個語句的語法。「Parser會把Lexer分析之后生成的token序列進行語法分析,并生成對應的一棵抽象語法樹(AST)」。之后,ByteCodeGenerator會根據AST來生成JSCore的字節碼,完成整個「語法解析」步驟。
JS源代碼經過了詞法分析和語法分析這兩個步驟,轉成了字節碼,其實就是經過任何一門程序語言必經的步驟–編譯。但是不同于我們編譯運行OC代碼,JS編譯結束之后,并不會生成存放在內存或者硬盤之中的目標代碼或可執行文件。生成的指令字節碼,會被立即被JSCore這臺虛擬機進行逐行「解釋執行」。運行指令字節碼(ByteCode)是JS引擎中很核心的部分,各家JS引擎的優化也主要集中于此。
PS:嚴格的講,語言本身并不存在編譯型或者是解釋型,因為語言只是一些抽象的定義與約束,并不要求具體的實現,執行方式。這里講JS是一門“解釋型語言”只是JS一般是被JS引擎動態解釋執行,而并不是語言本身的屬性。
如果對JavaScriptCore有更多興趣,關于JavaScriptCore的更多細節,建議延伸閱讀以下幾篇博文:
深入理解JSCore[13]
深入剖析 JavaScriptCore[14]
JavaScriptCore 全面解析[15]
深入淺出 JavaScriptCore[16]
瀏覽器與JavaScript
這一小結,還是以Chrome V8為例,簡單闡述瀏覽器與JavaScript的關系。
在?「V8 出現之前,所有的 JavaScript 虛擬機所采用的都是解釋執行的方式,這是 JavaScript 執行速度過慢的一個主要原因」。而 V8 率先引入了「即時編譯(JIT)**的**雙輪驅動」的設計(混合使用編譯器和解釋器的技術),這是一種權衡策略,「混合編譯執行和解釋執行這兩種手段」,給 JavaScript 的執行速度帶來了極大的提升。V8 出現之后,各大廠商也都在自己的 JavaScript 虛擬機中引入了 JIT 機制,所以目前市面上 JavaScript 虛擬機都有著類似的架構。另外,「V8 也是早于其他虛擬機引入了惰性編譯、內聯緩存、隱藏類等機制,進一步優化了 JavaScript 代碼的編譯執行效率」。
V8 執行一段 JavaScript 的流程
V8 執行一段 JavaScript 的流程如下圖所示:
V8執行一段JavaScript流程圖結合上文介紹的Chrome V8 架構,聚焦到JavaScript上,瀏覽器拿到JavaScript源碼,Parser,Ignition 以及 TurboFan 可以將 JS 源碼編譯為匯編代碼,其流程圖如下:
V8流程簡單地說,Parser 將 JS 源碼轉換為 AST,然后 Ignition 將 AST 轉換為 Bytecode,最后 TurboFan 將 Bytecode 轉換為經過優化的 Machine Code(實際上是匯編代碼)。
如果函數沒有被調用,則 V8 不會去編譯它。
如果函數只被調用 1 次,則 Ignition 將其編譯 Bytecode 就直接解釋執行了。TurboFan 不會進行優化編譯,因為它需要 Ignition 收集函數執行時的類型信息。這就要求函數至少需要執行 1 次,TurboFan 才有可能進行優化編譯。
如果函數被調用多次,則它有可能會被識別為「熱點函數」,且 Ignition 收集的類型信息證明可以進行優化編譯的話,這時 TurboFan 則會將 Bytecode 編譯為 Optimized Machine Code(已優化的機器碼),以提高代碼的執行性能。
圖片中的紅色虛線是逆向的,也就是說 Optimized Machine Code 會被還原為 Bytecode,這個過程叫做?「Deoptimization」。這是因為 Ignition 收集的信息可能是錯誤的,比如 add 函數的參數之前是整數,后來又變成了字符串。生成的 Optimized Machine Code 已經假定 add 函數的參數是整數,那當然是錯誤的,于是需要進行 Deoptimization。
function?add(x,?y)?{return?x?+?y; }add(1,?2); add('1',?'2');「V8 本質上是一個虛擬機」,因為計算機只能識別二進制指令,所以要讓計算機執行一段高級語言通常有兩種手段:
第一種是將高級代碼轉換為二進制代碼,再讓計算機去執行;
另外一種方式是在計算機安裝一個解釋器,并由解釋器來解釋執行。
解釋執行和編譯執行都有各自的優缺點,「解釋執行啟動速度快,但是執行時速度慢,而編譯執行啟動速度慢,但是執行速度快」。為了充分地利用解釋執行和編譯執行的優點,規避其缺點,「V8 采用了一種權衡策略,在啟動過程中采用了解釋執行的策略,但是如果某段代碼的執行頻率超過一個值,那么 V8 就會采用優化編譯器將其編譯成執行效率更加高效的機器代碼」。
簡單總結如下,「V8 執行一段 JavaScript 代碼所經歷的主要流程」包括:
初始化基礎環境;
解析源碼生成 AST 和作用域;
依據 AST 和作用域生成字節碼;
解釋執行字節碼;
監聽熱點代碼;
優化熱點代碼為二進制的機器代碼;
反優化生成的二進制機器代碼。
Chrome V8 的事件機制
關于異步編程和消息隊列,UI 線程提供一個消息隊列,并將待執行的事件添加到消息隊列中,然后 UI 線程會不斷循環地從消息隊列中取出事件、執行事件,通用 UI 線程宏觀架構如下圖所示:
v8-ui瀏覽器的不同形態
WebView
「WebView 是一種嵌入式瀏覽器,原生應用可以用它來展示網絡內容」。WebView 只是一個「可視化的」組件/控件/微件等。這樣我們可以用它來作為我們原生 app 的視覺部分。當你使用原生應用時,WebView 可能只是被隱藏在普通的原生 UI 元素中,你甚至用不到注意到它。
如果你把瀏覽器想象成兩部分,一部分是 UI(地址欄,導航欄按鈕等),其它部分是把標記跟代碼轉換成我們可見和可交互視圖的引擎。「WebView 就是瀏覽器引擎部分」,你可以像插入 iframe 一樣將 Webview 插入到你的原生應用中,并且編程化的告訴它將會加載什么網頁內容。
運行在你的 WebView 中的 JavaScript 有能力調用原生的系統 API。這意味著你不必受到 Web 代碼通常必須遵守的傳統瀏覽器安全沙箱的限制。下圖解釋了使用這種技術后的架構差異:
webview and webapp默認情況下,在 WebView 或 Web 瀏覽器中運行的任何 Web 代碼都與應用的其余部分保持隔離。這樣做是出于安全原因,主要是為降低惡意的 JavaScript 代碼對系統造成的傷害。對于任意 Web 內容,這種安全級別很有意義,因為你永遠不能完全信任加載的 Web 內容。但 WebView 的情況并非如此,對于 WebView 方案,開發人員通常可以完全控制加載的內容。惡意代碼進入并在設備上造成混亂的可能性非常低。
「這就是為什么對于 WebView,開發人員可以使用各種受支持的方式來覆蓋默認的安全行為,并讓 Web 代碼和原生應用代碼相互通信。這種溝通通常稱為 bridge」。你可以在上文的圖片中看到 bridge 可視化為 Native Bridge 和 JavaScript Bridge 的一部分。
WebView 非常好,雖然它看起來像是完全特殊和獨特的,但請記住,它們只不過是一個在應用中設置好位置和大小的、沒有任何花哨 UI 的瀏覽器,這就是它的精髓。大多數情況下,除非您調用原生 API,否則您不必在 WebView 中專門測試您的 Web 應用程序。此外,您在 WebView 中看到的內容與您在瀏覽器中看到的內容相同,尤其是使用同一渲染引擎時:
在 iOS 上,Web 渲染引擎始終是 WebKit,與 Safari 和 Chrome 相同。是的,你沒看錯。iOS 上的 Chrome 實際上使用了 WebKit。
在 Android 上的渲染引擎通常是 Blink,與 Chrome 相同。
在 Windows,Linux 和 macOS 上,由于這些是更寬松的桌面平臺,因此在選擇 WebView 風格和渲染引擎時會有很大的靈活性。你看到的流行渲染引擎將是 Blink(Chrome)和 Trident(Internet Explorer),但是沒有一個引擎可以依賴。這完全取決于應用以及它正在使用的 WebView 引擎。
WebView 的應用:
WebView 最常見的用途之一是顯示鏈接的內容;
廣告仍然是原生應用最流行的賺錢方式之一,大多數廣告是通過 WebView 提供的 Web 內容進行投放的;
Hybrid Apps,混合應用程序很受歡迎有幾個原因,最大的一個是提高開發人員的生產力。如果你有一個可以在瀏覽器中運行的響應式 Web 應用程序,那么讓相同的應用程序在各種設備上與混合應用程序一起運行是相當簡單的;當你對 Web 應用進行更新時,所有使用它的設備都可以立即使用該更改,因為內容來自一個集中的服務器,而如果是純原生應用,部署和更新時,你將不得不經歷針對每個平臺的構建、審核;
原生應用擴展,如 Microsoft Office 中類似維基百科這樣的基于網絡的擴展就是通過一個 WebView 實現的。
如果你對 WebView 感興趣,可通過以下幾篇文章繼續了解:
7.5.1 WebView(網頁視圖)基本用法[17]
Android:這是一份全面 & 詳細的Webview使用攻略[18]
Headless browser
「無頭瀏覽器」是一種未配置圖形用戶界面 (GUI) 的 Web 瀏覽器,通常通過命令行或網絡通信來執行。它主要由軟件測試工程師使用,沒有 GUI 的瀏覽器執行速度更快,因為它們不必繪制視覺內容。無頭瀏覽器的最大好處之一是它們能夠在沒有 GUI 支持的服務器上運行。
Headless 瀏覽器對于測試網頁特別有用,因為它們能夠像瀏覽器一樣呈現和理解超文本標記語言,包括頁面布局、顏色、字體選擇以及JavaScript和AJAX的執行等樣式元素,這些元素在使用其他測試方法時通常是不可用的。
Headless_architectureHeadless 瀏覽器有兩個主要可交付成果:
無頭庫,它允許嵌入應用程序控制瀏覽器并與網頁交互。
一個無頭外殼,它是一個示例應用程序,用于執行無頭 API 的各種功能。
Puppeteer 是一個 Node 庫,他提供了一組用來操縱 Chrome 的 API, 通俗來說就是一個 headless chrome 瀏覽器 (當然你也可以配置成有 UI 的,默認是沒有的)。既然是瀏覽器,那么我們手工可以在瀏覽器上做的事情 Puppeteer 都能勝任, 另外,Puppeteer 翻譯成中文是”木偶”意思,所以聽名字就知道,操縱起來很方便,你可以很方便的操縱她去實現:
1) 生成網頁截圖或者 PDF 2) 高級爬蟲,可以爬取大量異步渲染內容的網頁 3) 實現 UI 自動化測試,模擬鍵盤輸入、表單自動提交、點擊、登錄網頁等 4) 捕獲站點的時間線,以便追蹤你的網站,幫助分析網站性能問題 5) 模擬不同的設備 6) ...
Puppeteer 跟 webdriver 以及 PhantomJS 最大的 的不同就是它是站在用戶瀏覽的角度,而 webdriver 和 PhantomJS 最初設計就是用來做自動化測試的,所以它是站在機器瀏覽的角度來設計的,所以它們 使用的是不同的設計哲學。
Headless Chrome architecture[19]
puppeteer[20]
Puppeteer 入門教程[21]
結合項目來談談 Puppeteer[22]
Electron
Electron(原名為Atom Shell)是 GitHub 開發的一個開源框架。它通過使用 Node.js(作為后端)和Chromium 的渲染引擎(作為前端)完成跨平臺的桌面 GUI 應用程序的開發。現已被多個開源 Web 應用程序用于前端與后端的開發,著名項目包括 GitHub 的 Atom 和微軟的 Visual Studio Code。
ElectronElectron Architecture 由多個 Render Process 和一個 Main 進程組成。Main Process 啟動Render Process,它們之間的通信是通過IPC [Inter Process Communication],如下圖所示。
Electron_Architecture我們常用的IDE VSCode 就是基于 Electron (原來叫 Atom Shell) 進行開發的。如下圖所示,(點擊 VSCode 幫助【Help】 下的 切換開發人員工具即可打開以下面板)。
VSCodeVS Code 的其他的主要組件有:
殼:Monaco Editor[23]
內核:Language Server Protocol[24](一個代碼編輯器)
Debug Adapter Protocol[25]
Xterm.js[26]
延伸閱讀:Electron | Build cross-platform desktop apps with JavaScript, HTML, and CSS[27]
瀏覽器代碼兼容性測試
caniuse[28]
browseemall[29]
html5test[30]
延伸閱讀
瀏覽器簡史[31]
Web 瀏覽器相關的一些概念[32]
瀏覽器的工作原理:新式網絡瀏覽器幕后揭秘[33]
從瀏覽器多進程到 JS 單線程,JS 運行機制最全面的一次梳理[34]
???? 移動端 JS 引擎哪家強?美國硅谷找......
從 V8 角度揭秘你不知道的面試八股文
高性能 JavaScript 引擎 V8 - 垃圾回收
Inside look at modern web browser[35]【一共四篇,可供參考】
參考資料
Inside look at modern web browser[36]
瀏覽器是如何工作的:Chrome V8 讓你更懂 JavaScript[37]
深入理解JSCore[38]
The Story of the Web: A History Of Internet Browsers[39]
PPT - Browser Architecture[40]
JavaScript 引擎 V8 執行流程概述[41]
Understanding WebViews[42]
Quantum Up Close: What is a browser engine?[43]
本文首發于個人博客[44],歡迎指正和star[45]。
參考資料
[1]
瀏覽器市場份額:https://link.juejin.cn/?target=https%3A%2F%2Ftongji.baidu.com%2Fresearch%2Fsite
[2]全球瀏覽器市場份額:https://link.juejin.cn/?target=https%3A%2F%2Fgs.statcounter.com%2F
[3]w3counter:https://link.juejin.cn/?target=https%3A%2F%2Fwww.w3counter.com%2Fglobalstats.php
[4]Chrome 為什么多進程而不是多線程?:https://link.juejin.cn/?target=https%3A%2F%2Fwww.zhihu.com%2Fquestion%2F368712837
[5]經典面試題:從 URL 輸入到頁面展現到底發生什么?:https://link.juejin.cn/?target=https%3A%2F%2Fzhuanlan.zhihu.com%2Fp%2F57895541
[6]在瀏覽器輸入 URL 回車之后發生了什么(超詳細版):https://link.juejin.cn/?target=https%3A%2F%2Fzhuanlan.zhihu.com%2Fp%2F80551769
[7]萬字詳文:深入理解瀏覽器原理:https://link.juejin.cn/?target=https%3A%2F%2Fzhuanlan.zhihu.com%2Fp%2F96986818
[8]參考閱讀:https://link.juejin.cn/?target=https%3A%2F%2Fsegmentfault.com%2Fa%2F1190000037435824
[9]Parser:https://link.juejin.cn/?target=https%3A%2F%2Fv8.dev%2Fblog%2Fscanner
[10]Ignition:https://link.juejin.cn/?target=https%3A%2F%2Fv8.dev%2Fdocs%2Fignition
[11]TurboFan:https://link.juejin.cn/?target=https%3A%2F%2Fv8.dev%2Fdocs%2Fturbofan
[12]Orinoco:https://link.juejin.cn/?target=https%3A%2F%2Fv8.dev%2Fblog%2Ftrash-talk
[13]深入理解JSCore:https://link.juejin.cn/?target=https%3A%2F%2Ftech.meituan.com%2F2018%2F08%2F23%2Fdeep-understanding-of-jscore.html
[14]深入剖析 JavaScriptCore:https://link.juejin.cn/?target=https%3A%2F%2Fming1016.github.io%2F2018%2F04%2F21%2Fdeeply-analyse-javascriptcore%2F
[15]JavaScriptCore 全面解析:https://juejin.cn/post/6844903765582053384
[16]深入淺出 JavaScriptCore:https://link.juejin.cn/?target=https%3A%2F%2Fwww.jianshu.com%2Fp%2Fac534f508fb0
[17]7.5.1 WebView(網頁視圖)基本用法:https://link.juejin.cn/?target=https%3A%2F%2Fwww.runoob.com%2Fw3cnote%2Fandroid-tutorial-webview.html
[18]Android:這是一份全面 & 詳細的Webview使用攻略:https://link.juejin.cn/?target=https%3A%2F%2Fwww.jianshu.com%2Fp%2F3c94ae673e2a%2F
[19]Headless Chrome architecture:https://link.juejin.cn/?target=https%3A%2F%2Fwww.cnblogs.com%2Fbigben0123%2Fp%2F13880254.html
[20]puppeteer:https://link.juejin.cn/?target=https%3A%2F%2Fgithub.com%2Fpuppeteer%2Fpuppeteer%2F
[21]Puppeteer 入門教程:https://link.juejin.cn/?target=https%3A%2F%2Fwww.r9it.com%2F20171106%2Fpuppeteer.html
[22]結合項目來談談 Puppeteer:https://link.juejin.cn/?target=https%3A%2F%2Fzhuanlan.zhihu.com%2Fp%2F76237595
[23]Monaco Editor:https://link.juejin.cn/?target=https%3A%2F%2Fgithub.com%2FMicrosoft%2Fmonaco-editor
[24]Language Server Protocol:https://link.juejin.cn/?target=https%3A%2F%2Fgithub.com%2FMicrosoft%2Flanguage-server-protocol
[25]Debug Adapter Protocol:https://link.juejin.cn/?target=https%3A%2F%2Fgithub.com%2FMicrosoft%2Fdebug-adapter-protocol
[26]Xterm.js:https://link.juejin.cn/?target=https%3A%2F%2Fxtermjs.org%2F
[27]Electron | Build cross-platform desktop apps with JavaScript, HTML, and CSS:https://link.juejin.cn/?target=https%3A%2F%2Fdelftswa.gitbooks.io%2Fdesosa2018%2Fcontent%2Felectron%2Fchapter.html
[28]caniuse:https://link.juejin.cn/?target=https%3A%2F%2Fwww.caniuse.com%2F
[29]browseemall:https://link.juejin.cn/?target=https%3A%2F%2Fwww.browseemall.com%2FResources
[30]html5test:https://link.juejin.cn/?target=https%3A%2F%2Fhtml5test.com%2F
[31]瀏覽器簡史:https://link.juejin.cn/?target=http%3A%2F%2Fwww.cnw.com.cn%2Fzhuanti%2F2009-ie%2F
[32]Web 瀏覽器相關的一些概念:https://link.juejin.cn/?target=https%3A%2F%2Fkeqingrong.cn%2Fblog%2F2019-11-24-concepts-related-to-web-browsers
[33]瀏覽器的工作原理:新式網絡瀏覽器幕后揭秘:https://link.juejin.cn/?target=https%3A%2F%2Fwww.html5rocks.com%2Fzh%2Ftutorials%2Finternals%2Fhowbrowserswork%2F
[34]從瀏覽器多進程到 JS 單線程,JS 運行機制最全面的一次梳理:https://link.juejin.cn/?target=https%3A%2F%2Fsegmentfault.com%2Fa%2F1190000012925872
[35]Inside look at modern web browser:https://link.juejin.cn/?target=https%3A%2F%2Fdevelopers.google.com%2Fweb%2Fupdates%2F2018%2F09%2Finside-browser-part1
[36]Inside look at modern web browser:https://link.juejin.cn/?target=https%3A%2F%2Fdevelopers.google.com%2Fweb%2Fupdates%2F2018%2F09%2Finside-browser-part1
[37]瀏覽器是如何工作的:Chrome V8 讓你更懂 JavaScript:https://link.juejin.cn/?target=https%3A%2F%2Fsegmentfault.com%2Fa%2F1190000037435824
[38]深入理解JSCore:https://link.juejin.cn/?target=https%3A%2F%2Ftech.meituan.com%2F2018%2F08%2F23%2Fdeep-understanding-of-jscore.html
[39]The Story of the Web: A History Of Internet Browsers:https://link.juejin.cn/?target=https%3A%2F%2Fwww.internetadvisor.com%2Fthe-story-of-the-web-a-history-of-internet-browsers
[40]PPT - Browser Architecture:https://link.juejin.cn/?target=https%3A%2F%2Fsangbui.com%2Fsb-files%2FBrowserArchitecture_ClientSide.pdf
[41]JavaScript 引擎 V8 執行流程概述:https://link.juejin.cn/?target=http%3A%2F%2Fblog.itpub.net%2F69912579%2Fviewspace-2668277%2F
[42]Understanding WebViews:https://link.juejin.cn/?target=https%3A%2F%2Fwww.kirupa.com%2Fapps%2Fwebview.htm
[43]Quantum Up Close: What is a browser engine?:https://link.juejin.cn/?target=https%3A%2F%2Fhacks.mozilla.org%2F2017%2F05%2Fquantum-up-close-what-is-a-browser-engine%2F
[44]個人博客:https://link.juejin.cn/?target=https%3A%2F%2Fking-hcj.github.io%2F2021%2F07%2F11%2Fweb-browser%2F
[45]指正和star:https://link.juejin.cn/?target=https%3A%2F%2Fgithub.com%2Fking-hcj%2Fking-hcj.github.io
- END -
看完一鍵三連在看,轉發,點贊
是對文章最大的贊賞,極客重生感謝你
推薦閱讀
開源, yyds!
終于有人把云計算、大數據和人工智能講明白了!
硬核致敬Linux !30歲生日快樂!
總結
以上是生活随笔為你收集整理的深入理解浏览器原理和架构|硬核的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 攻克数据结构与算法
- 下一篇: TCP/IP协议栈到底是内核态好还是用户