47 張圖帶你走進瀏覽器的世界!
大家好,我是零一
,每個開發者(尤其是前端工程師)或多或少會跟瀏覽器打交道,那麼你們有沒有想過去深入瞭解瀏覽器呢?無論是因爲好奇還是爲了面試,相信你們一定在網上搜過不少關於瀏覽器相關的知識和文章,或者也買過不少的課程。但很少有文章能生動形象地帶你去了解瀏覽器的點點滴滴。
今天就給大家帶來一篇我同事 獨釣寒江雪 帶來的🔥萬字精品文章
,他是思否的優秀作者,輸出多篇硬核文章,感興趣的朋友可以點擊文章末尾的「閱讀原文」進行查看~
作者:獨釣寒江雪
原文鏈接:https://juejin.cn/post/6983896089703235592
本文用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-Browsers
1990 年瀏覽器誕生之後的故事,想必您已經早有耳聞:
-
「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 的瀏覽器),這使其能夠在市場上佔據一席之地並不斷髮展壯大,最終在瀏覽器領域取得了勝利,這便是著名的**「第一次瀏覽器大戰」**。
Market_Share_During_the_Browser_Wars
市場份額的快速下滑導致 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 核心作爲辦公人員,坐在辦公桌前處理各自的工作:
CPU
GPU
圖形處理器(Graphics Processing Unit,簡稱爲 GPU)是計算機的另一部件。與 CPU 不同,GPU 擅長同時處理跨內核的簡單任務。顧名思義,「它最初是爲解決圖形而開發的」。這就是爲什麼在圖形環境中 “使用 GPU” 或 “GPU 支持” 都與快速渲染和順滑交互有關。近年來隨着 GPU 加速計算的普及,僅靠 GPU 一己之力也使得越來越多的計算成爲可能。
下圖中,許多帶特定扳手的 GPU 內核意味着它們只能處理有限任務。
GPU
進程與線程
進程可以被描述爲是一個應用的執行程序。線程是位於進程內部並執行其進程程序的任意部分。
啓動應用時會創建一個進程。程序也許會創建一個或多個線程來幫助它工作。操作系統爲進程提供了一個可以使用的 “一塊” 內存,所有應用程序狀態都保存在該私有內存空間中。關閉應用程序時,相應的進程也會消失,操作系統會釋放內存(下圖中,邊界框爲進程,線程作爲抽象魚在進程中游動)。
memory
進程可以請求操作系統啓動另一個進程來執行不同的任務。此時,內存中的不同部分會分給新進程。如果兩個進程需要對話,他們可以通過 ** 進程間通信(IPC)** 來進行。許多應用都是這樣設計的,所以如果一個工作進程失去響應,該進程就可以在不停止應用程序不同部分的其他進程運行的情況下重新啓動。
workerprocess.gif
瀏覽器的進程 / 線程架構模型
瀏覽器進程分類
關於如何**「構建 web 瀏覽器並不存在標準規範」**,一個瀏覽器的構建方法可能與另一個迥然不同。不同瀏覽器的進程 / 線程架構一般由下圖幾部分:
browser-arch
Chrome 多進程架構
而當下 “瀏覽器世界的王者” Chrome 架構如下圖所示,渲染進程下顯示了多個層,表明 Chrome 爲每個標籤頁運行多個渲染進程。
browser-arch-chrome
上圖中,頂部是瀏覽器進程,它與處理應用其它模塊任務的進程進行協調。對於渲染進程來說,創建了多個渲染進程並分配給了每個標籤頁。Chrome 在可能的情況下會給每個標籤頁分配一個進程。而現在它試圖給每個站點分配一個進程,包括 iframe。
-
瀏覽器進程:控制應用中的 “Chrome” 部分,包括地址欄,書籤,回退與前進按鈕,以及處理 web 瀏覽器中網絡請求、文件訪問等不可見的特權部分;
-
渲染進程:控制標籤頁內網站展示;
-
插件進程:控制站點使用的任意插件,如 Flash;
-
GPU 進程:處理獨立於其它進程的 GPU 任務。GPU 被分成不同進程,因爲 GPU 處理來自多個不同應用的請求並繪製在相同表面。
可以簡單理解爲不同進程對應瀏覽器 UI 的不同部分:
browserui
「Chrome 更多的是把自己抽象爲一個操作系統,網頁或擴展相當於一個個程序」,你甚至可以發現,Chrome 確實自帶了一個任務管理器,在任務管理器面板會列出當前正在運行的進程以及它們當前的 CPU / 內存使用量情況等信息。
一般你可以通過兩種方法打開 Chrome 任務管理器:
-
通過在瀏覽器頂欄(標籤 tab 欄)右側右鍵,選擇任務管理器查看;
-
點擊 Chrome 瀏覽器右上角的 “選項” 菜單(一般是三個點的標識),選擇 “更多工具” 子菜單,點擊“任務管理器”,打開任務管理器窗口。
task
前文中提到了 Chrome 使用多個渲染進程,那他有什麼優勢呢?
- 穩定性:最簡單的情況下,你可以想象每個標籤頁都有自己的渲染進程。假設你打開了三個標籤頁,每個標籤頁都擁有自己獨立的渲染進程。如果某個標籤頁失去響應,你可以關掉這個標籤頁,此時其它標籤頁依然運行着,可以正常使用。如果所有標籤頁都運行在同一進程上,那麼當某個失去響應,所有標籤頁都會失去響應,顯然這樣的體驗會很糟糕。下面是多 / 單進程架構的對比動圖,供你參考。
tabs.gif
- 安全性與沙箱化:把瀏覽器工作分成多個進程的另一好處是安全性與沙箱化。由於操作系統提供了限制進程權限的方法,瀏覽器就可以用沙箱保護某些特定功能的進程。例如,Chrome 瀏覽器可以限制處理用戶輸入(如渲染器)的進程的文件訪問的權限。
由於進程有自己的私有內存空間,所以它們通常包含公共基礎設施的拷貝 (如 Chrome V8 引擎)。這意味着使用了更多的內存,如果它們是同一進程中的線程,就無法共享這些拷貝(同一個進程中的線程不共享堆棧,堆棧是保證線程獨立運行所必須的)。爲了節省內存,Chrome 對可啓動的進程數量有所限制。具體限制數值依設備可提供的內存與 CPU 能力而定,但是**「當 Chrome 運行時達到限制時,會開始在同一站點的不同標籤頁上運行同一進程」**。
Chrome 正在經歷架構變革,它轉變爲將瀏覽器程序的每一模塊作爲一個服務來運行,從而可以輕鬆實現進程的拆解或聚合。具體表現是,當 Chrome 運行在**「強力硬件」**上時,它會將每個服務分解到不同進程中,從而**「提升穩定性」**,但是如果 Chrome 運行在資源有限的設備上時,它會將服務聚合到一個進程中從而**「節省了內存佔用」**。在這一架構變革實現前,類似的整合進程以減少內存使用的方法已經在 Android 類平臺上使用。
servicfication.gif
Chrome 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 爲穩定版。
chromium 架構
圖片來源:萬字詳文:深入理解瀏覽器原理 [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 有個整體的瞭解:
WebKit
WebKit 就是一個**「頁面渲染以及邏輯處理引擎」**,前端工程師把 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_Mosaic
Firefox 架構:
Architecture_of_Mozilla
Chrome 架構:
Architecture_of_Chrome
Safari 架構:
Architecture_of_Safari
IE 架構:
IE 架構
瀏覽器基本原理
Chrome V8
V8 一詞最早見於 “V-8 engine”,即 V8 發動機,一般使用在中高端車輛上。8 個氣缸分成兩組,每組 4 個,成 V 型排列。是高層次汽車運動中最常見的發動機結構,尤其在美國,IRL,ChampCar 和 NASCAR 都要求使用 V8 發動機。
關於 Chrome V8,筆者曾有一篇筆記做了比較詳細的介紹,全文脈絡如下,感興趣可以參考閱讀 [8]。
Chrome-V8
V8 是依託 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“的過程,具體流程如下:
Scanner
-
Ignition[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 樹,並與之交互。我們可以通過下圖看下它的工作流程:
JavaScriptCore
JavaScriptCore 主要模塊:「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_architecture
Headless 瀏覽器有兩個主要可交付成果:
-
無頭庫,它允許嵌入應用程序控制瀏覽器並與網頁交互。
-
一個無頭外殼,它是一個示例應用程序,用於執行無頭 API 的各種功能。
Architecture_of_Puppeteer
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。
Electron
Electron Architecture 由多個 Render Process 和一個 Main 進程組成。Main Process 啓動 Render Process,它們之間的通信是通過 IPC [Inter Process Communication],如下圖所示。
Electron_Architecture
我們常用的 IDE VSCode 就是基於 Electron (原來叫 Atom Shell) 進行開發的。如下圖所示,(點擊 VSCode 幫助【Help】 下的 切換開發人員工具即可打開以下面板)。
VSCode
VS 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
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/cnE9UaM5v8Q4rbKdB00KiA