Electron架構(gòu)深入探究
Electron是什么
引用來自官網(wǎng)的解釋:
Electron 是一個使用 JavaScript、 HTML 和 CSS 構(gòu)建桌面應(yīng)用程序的框架。通過將 Chromium 和 Node.js 嵌入到它的二進制文件中,Electron 允許你維護一個 JavaScript 代碼庫,并創(chuàng)建可以在 Windows、 macOS 和 Linux 上運行的跨平臺應(yīng)用程序ーー不需要本地開發(fā)經(jīng)驗。
如果我們追溯歷史,可以發(fā)現(xiàn)Electron
的前身是Atom Shell
,最開始的設(shè)計目標(biāo)就是為Atom
編輯器而生,實際上Electron
的作者之前也是node-webkit
的核心貢獻者,而node-webkit
正是NW.js
的前身。在作者離開英特爾公司(當(dāng)初大力支持node-webkit
)后,就加入了Github
項目組,孵化了Atom Shell
這個項目,再到后來(2014年)正式更名為Electron
,發(fā)展至今。
Electron
和眾多類似的產(chǎn)品目標(biāo)非常簡單,他們將chromium
(這里不同的框架選擇不同,比如Tauri
選擇了原生的WebView
,而WebView2
選擇了Edge
內(nèi)核)和Node.js
(這里不同框架采取策略也不同,比如Webview2
不提供默認的運行時,而Tauri
選擇了Rust
等等)利用C++
等原生語言集成起來,提供了一整套基于Web
的運行環(huán)境,并提供了與底層OS
交互的便捷API
,目的就是為了讓大家使用Web
的技術(shù)棧去開發(fā)客戶端原生應(yīng)用,從而實現(xiàn)不同操作系統(tǒng)之間的跨平臺開發(fā)。
說起桌面端GUI跨平臺開發(fā)不得不提到Qt
,這個使用C++
來統(tǒng)一各個平臺開發(fā)的框架才能被稱為桌面跨端開發(fā)的鼻祖。在之前每個操作系統(tǒng)都是各自為戰(zhàn),經(jīng)歷過windows
時代的MFC
、WPF
的開發(fā)模式,在Mac
上則是OC
、Swift
作為底層語言,在經(jīng)歷了互聯(lián)網(wǎng)時代變遷后,跨端框架越來越被大家所喜愛,廣泛運用于互聯(lián)網(wǎng)產(chǎn)品中。
若論起性能,肯定是越接近底層的語言開發(fā)出來的軟件性能越高。如果要追溯歷史,最底層的編程方式大概是最早的紙帶打孔編碼的時代,那時的人們是真正的編程大師,在用機器碼編程,寫二進制程序是非常復(fù)雜的,只通過0和1兩個數(shù)字完成如此復(fù)雜的邏輯代碼,基本上是需要巨大的精力和時間的,所以這個時代的程序只能做非常簡單的事情。到后來匯編語言的產(chǎn)生才能讓一些操作逐漸復(fù)雜一些,但依舊無法完成更復(fù)雜的架構(gòu)設(shè)計。直到高級語言的出現(xiàn),才讓軟件世界逐漸豐富多彩了起來,在計算機上產(chǎn)生了令人震驚的軟件和操作系統(tǒng),進入個人電腦時代,改變了世界。
在高級語言中,C語言應(yīng)該是最接近底層的開發(fā)語言了,因此常用的操作系統(tǒng)內(nèi)核基本都是用C語言和匯編寫成,這是因為內(nèi)核需要極高的性能以及對底層硬件驅(qū)動的精確控制。后來經(jīng)過工程師在工程方面的不斷探索,有了面向?qū)ο螅幊谭妒?,有更高層利于維護的語言出現(xiàn)。C++可以說是介于C和更高級語言之間的一個產(chǎn)物,它完全兼容C的語法,又添加了面向?qū)ο?、STL模板等能力,讓他在能擁有不俗的性能的同時,還擁有一定的大型工程化的能力,我們所了解到的大多數(shù)最復(fù)雜的軟件,比如瀏覽器Chrome、Office、編譯器、游戲等等,尤其是最復(fù)雜的瀏覽器軟件,瀏覽器內(nèi)核的復(fù)雜程度遠超我們想象,也正是有chromium
這樣的開源貢獻,造就了今天互聯(lián)網(wǎng)時代的技術(shù)繁榮,基于V8
和LibUV
構(gòu)建的Node.js
讓前端迅速發(fā)展到一個不可思議的地步,本文所講的Electron
也同樣依賴于這樣的技術(shù)。
回到性能的討論,毫無疑問在引入了chromium
和Node.js
作為運行時的Electron
性能是不如基于C++
的Qt
,同樣Qt
的性能也不及直接使用原生語言來開發(fā)的程序,多一層抽象的封裝必然會折損一部分性能。那是不是說用性能越好的語言來開發(fā)就是最優(yōu)的呢?答案顯然不是,不然現(xiàn)在我們應(yīng)該直接用機器碼來開發(fā)。實際上,軟件語言和框架的發(fā)展,離不開硬件的高速發(fā)展,硬件遵循著摩爾定律發(fā)展至今,硬件的計算能力、存儲能力都有著飛躍式的進步,這才能夠讓軟件脫離底層的束縛,越來越專注于工程的可維護性和易用性,釋放掉一些不必要的生產(chǎn)力,讓軟件的世界發(fā)展到今天這種繁榮的地步。
毫無疑問,Electron
是處于最上層的抽象層級當(dāng)中,通過簡單高效的Web技術(shù)來實現(xiàn)復(fù)雜的桌面軟件開發(fā)。從語言發(fā)展的視角來看,C和C++可以對內(nèi)存進行精細地控制訪問,而底層的匯編則更可以操縱寄存器,存儲越靠近CPU運行速度就會越快。但是它帶來的代價是昂貴的開發(fā)成本和安全問題,還記得在windows時代有著各種蠕蟲木馬病毒,很大一部分都是程序本身的緩沖區(qū)溢出、訪問越界等等問題,這類底層的語言對開發(fā)人員的要求較高,需要能夠掌握操作系統(tǒng)的內(nèi)部機制,在大型工程的情況下,bug是難免的,而底層語言造成的bug往往影響面更大。因此后來Java
等語言去除了指針的設(shè)計,弱化了對內(nèi)存的控制程度,增強了工程化的能力,以更好地應(yīng)對復(fù)雜的軟件環(huán)境。再到后來python
、javascript
等腳本語言的流行,更簡化了開發(fā)人員編寫代碼的成本,涌現(xiàn)多種編程范式和繁榮的生態(tài)。而新興的現(xiàn)代化編程語言如golang
、rust
等則是性能與易用之間的權(quán)衡,從這個發(fā)展趨勢來看,大家一直在探尋著一個平衡點。
從另一個角度來看,軟件的研發(fā)成本和產(chǎn)品、商業(yè)也息息相關(guān),行業(yè)巨頭Google、微軟、IBM等大型軟件公司,都曾面臨過無法按時交付的問題。人月神話中也深刻地揭示了軟件開發(fā)的工期不是靠純堆人力就能將問題解決的,一旦有這類風(fēng)險產(chǎn)生,無論是對企業(yè)還是用戶都會造成比較大的傷害。而越是底層的語言,所需要軟件開發(fā)人員的專業(yè)素質(zhì)越高,維護成本也就越高,因此在互聯(lián)網(wǎng)高速發(fā)展的時代,系統(tǒng)開發(fā)相關(guān)的人才不斷減少,更多涌現(xiàn)出大量的應(yīng)用開發(fā)人員,進入Web高速發(fā)展的階段。這是由于互聯(lián)網(wǎng)業(yè)務(wù)的高速發(fā)展、軟硬件技術(shù)的不斷迭代更新,形成的一種趨勢。因此Electron
、React Native
、Flutter
、uniApp
、Taro
這類跨端解決方案越來越受大家歡迎也是必然的結(jié)果。
Electron架構(gòu)
ElectronJS 進程模型圖解
Electron
的架構(gòu)設(shè)計很大程度上是受到Chromium
的啟發(fā)。Chromium
是Google
開源的瀏覽器內(nèi)核代碼,Chrome
、Edge
、Opera
等等瀏覽器都是基于Chromium
來實現(xiàn)的。Chromium
堪稱是全世界最復(fù)雜的軟件應(yīng)用,整體代碼庫已經(jīng)龐大到了近40G,我們簡單舉個例子說明下其復(fù)雜程度:
net
模塊,實現(xiàn)了主機解析,cookies,網(wǎng)絡(luò)改變探測,SSL,資源緩存,ftp,HTTP, OCSP實現(xiàn),代理 (SOCKS和HTTP) 配置,解析,腳本獲?。òǜ鞣N不同系統(tǒng)下實現(xiàn)),QUIC,socket池,SPDY,WebSockets等等,每套協(xié)議都是十分復(fù)雜的。v8
模塊,包括字節(jié)碼解析器,JIT 編譯器,多代GC,inspector (調(diào)試支持),內(nèi)存和 CPU 的 profiler(性能統(tǒng)計),WebAssembly 支持,兩種 post-mortem diagnostics 的支持,啟動快照,代碼緩存、代碼熱點分析等等。Skia
模塊,用點畫出各種圖。然而里面包括十幾種矢量的繪制,文字繪制、GPU加速、矢量的指令錄制以及回放(還要能支持線程安全)、各種圖像格式的編解碼、GPU渲染優(yōu)化等等。Blink
內(nèi)核,這個更復(fù)雜,HTML
和CSS
規(guī)范就得近萬頁了,要將它們完全實現(xiàn)是一個巨大的工作量,再加上實現(xiàn)Layout
的成本,涉及到非常龐大的計算,還要考慮極致的性能,保證瀏覽器的渲染能夠流暢快速。- 還有音視頻相關(guān)、沙箱、插件、UI等等,就不贅述了,總之稱之為巨型軟件應(yīng)用也不為過,
正是由于這一龐大復(fù)雜架構(gòu)的開源,經(jīng)過數(shù)年的不斷打磨完善,讓W(xué)eb技術(shù)能夠快速發(fā)展,百花齊放。
我們知道,在瀏覽器內(nèi)部有很多的處理模塊,這些模塊的代碼可以采用進程或者線程的方式來進行組織調(diào)度:
browser architecture
在瀏覽器實現(xiàn)方面是沒有標(biāo)準(zhǔn)規(guī)范的,這取決于不同瀏覽器內(nèi)部的實現(xiàn)細節(jié)。在最早期,瀏覽器渲染都是在同一個進程里面完成的,后來Chrome
采用了多進程架構(gòu),演變成了這種模式:
browser architecture
其中:
- 瀏覽器主進程,實現(xiàn)瀏覽器的主要UI、負責(zé)和文件、網(wǎng)絡(luò)等等操作系統(tǒng)底層接口對接通信。
- 渲染進程,每一個
tab
獨立開一個渲染進程,核心進行web代碼解析和渲染工作。 - 插件進程,負責(zé)瀏覽器插件的控制。
- GPU進程,獨立的進程負責(zé)處理GPU圖像的渲染繪制。
這樣設(shè)計架構(gòu)的好處主要有兩個:
- 保證每個tab獨立進程,這樣在某一個頁面
crash
的時候,僅僅影響當(dāng)前的Tab,而不至于讓整個瀏覽器崩潰。這提升了軟件的健壯性和用戶體驗。 - 有利于實現(xiàn)沙箱隔離的安全機制,基于進程可以很方便地控制不同頁面之間的安全訪問策略,確保每個
renderer
進程在自己單獨的沙箱環(huán)境內(nèi)安全地運行。
不過這類架構(gòu)也帶來一個額外的成本,那就是更多的內(nèi)存消耗,因為每一個進程需要開辟獨立的內(nèi)存空間,不同進程之間的內(nèi)存很難做到共享。因此這個策略也是個權(quán)衡的策略考慮,Chrome
基于用戶當(dāng)前的CPU
和內(nèi)存的情況,對進程的數(shù)量進行了動態(tài)的限制,以確保達到一個最佳的效果。
Electron
本身參考了這個架構(gòu)的實現(xiàn),將各個GUI窗口通過renderer
進程實現(xiàn),交由chromium
來加載渲染,主進程集成Node.js
,負責(zé)與系統(tǒng)API交互,處理核心事務(wù)。
我們可以從Electron
源碼結(jié)構(gòu)上很清晰地看到這點:
Electron ├── build/ - 構(gòu)建相關(guān) ├── buildflags/ - feature flag ├── chromium_src/ - chromium的一份拷貝(源碼僅包含build文件) ├── default_app/ - 默認啟動時的app程序 ├── docs/ -文檔 ├── lib/ - 使用JS/TS編寫的模塊 | ├── browser/ - 主進程初始化相關(guān) | | ├── api/ - 主進程暴露的API,通過_linkedBinding調(diào)用C++模塊 | ├── common/ - 主進程和渲染進程共用代碼 | | └── api/ - 主進程和渲染進程共同暴露的API | ├── renderer/ - 渲染進程初始化相關(guān) | | ├── api/ - 渲染進程API | | └── web-view/ - webview相關(guān)邏輯 ├── patches/ - 關(guān)于依賴的一些patch,主要是chromium、node、v8的 ├── shell/ - C++編寫的模塊 | ├── app/ - 入口 | ├── browser/ - 主進程相關(guān) | | ├── ui/ - 系統(tǒng)UI組件的一些實現(xiàn) | | ├── api/ - 主進程API實現(xiàn) | | ├── net/ - 網(wǎng)絡(luò)相關(guān)實現(xiàn) | | ├── mac/ - Mac系統(tǒng)下的一些實現(xiàn)(OC實現(xiàn)) | ├── renderer/ - 渲染進程相關(guān) | | └── api/ - 渲染進程API實現(xiàn) | └── common/ - 主進程渲染進程通用實現(xiàn) | └── api/ - 主進程渲染進程通用API實現(xiàn) └── BUILD.gn - 構(gòu)建入口
Electron
在源碼上與Node.js
實現(xiàn)類似,lib
目錄使用js
實現(xiàn),通過_linkedBinding
來調(diào)用C++
的模塊,在一開始會被編譯進內(nèi)存中,通過C++
程序裝在啟動。
C++
啟動入口在shell/app/electron_library_main.mm
:
int ElectronMain(int argc, char* argv[]) { electron::ElectronMainDelegate delegate; content::ContentMainParams params(&delegate); params.argc = argc; params.argv = const_cast<const char**>(argv); electron::ElectronCommandLine::Init(argc, argv); return content::ContentMain(std::move(params)); }
這里依賴的content
實際上是chromium
的content
模塊,chromium
將瀏覽器主進程部分和渲染進程進行了抽象,主進程部分的邏輯在blink
模塊實現(xiàn),而渲染進程相關(guān)的實現(xiàn)則封裝在content
模塊。
所以這里調(diào)用content
就可以使用chromium
的renderer
進程來進行啟動渲染了。
關(guān)于C++
部分的核心實現(xiàn)會在后續(xù)文章中進一步探討。
小結(jié)
Electron
本質(zhì)上就是集成Node.js
和Chromium
提供了基于Web技術(shù)棧開發(fā)客戶端軟件的能力,通過Web技術(shù)棧的快速迭代和Chrome本身的向前兼容迭代能力,可以做到跨平臺的快速迭代開發(fā)。
在軟件發(fā)展的進程中,我們始終在平衡軟硬件之間的性能關(guān)系,性能與成本的平衡,軟件維護和生態(tài)的持續(xù)發(fā)展,基于互聯(lián)網(wǎng)的發(fā)展,Web技術(shù)的發(fā)展,促成了Electron
這樣的跨端技術(shù)被廣泛應(yīng)用。
Electron
在實現(xiàn)架構(gòu)上參考了Chromium
的核心設(shè)計思想,通過主進程進行核心的調(diào)度啟動,不同的GUI窗口獨立渲染進程,并提供沙箱安全機制,做到進程間的隔離,進程與進程之間實現(xiàn)了IPC
通信機制,對主進程提供Node.js
運行時,封裝上層API,通過C++提供具體系統(tǒng)組件、系統(tǒng)方法能力的實現(xiàn)。
以上就是Electron架構(gòu)深入探究的詳細內(nèi)容,更多關(guān)于Electron架構(gòu)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
VSCode通過Ctrl+P快速打開node_modules中的文件的操作方法
由于node_modules目錄包含的文件太多,在VSCode中默認情況下是禁止搜索node_modules目錄的,在這種情況下,我們將不得不依次展開node_modules的文件目錄樹,來查找我們所需要的文件,接下來介紹VSCode如何通過Ctrl+P快速打開node_modules中的文件,需要的朋友可以參考下2023-07-07詳解nodejs express下使用redis管理session
本篇文章主要介紹了詳解nodejs express下使用redis管理session ,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-04-04如何用node.js作為后臺,讀寫xml文件,Node.js的文件系統(tǒng)的Api
這篇文章主要介紹了如何用node.js作為后臺,讀寫xml文件,Node.js的文件系統(tǒng)的Api,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08node.js利用redis數(shù)據(jù)庫緩存數(shù)據(jù)的方法
Redis數(shù)據(jù)庫采用極簡的設(shè)計思想,最新版的源碼包還不到2Mb。其在使用上也有別于一般的數(shù)據(jù)庫。下面這篇文章就來給大家介紹了node.js利用redis數(shù)據(jù)庫緩存數(shù)據(jù)的方法,需要的朋友可以參考借鑒,下面來一起看看吧。2017-03-03Node.js中Sequelize?hook的使用方法小結(jié)
Sequelize?提供了多個?hook,用于在執(zhí)行數(shù)據(jù)庫操作時執(zhí)行一些自定義邏輯,本文為大家整理了一些常用的?Sequelize?hook?列表及其作用,希望對大家有所幫助2024-02-02Node.js多文件Stream合并,串行和并發(fā)兩種模式的實現(xiàn)方式
這篇文章主要介紹了Node.js多文件Stream合并,串行和并發(fā)兩種模式的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10