一起來(lái)聊聊關(guān)于WebIDE的實(shí)現(xiàn)
本期聊聊WebIDE的概念和在各種客戶(hù)端的應(yīng)用場(chǎng)景;一起探討在社區(qū)里比較主流的WebIDE實(shí)現(xiàn)的方法模式與對(duì)比,一起來(lái)了解WebContainer思路下的WebIDE。
(本篇內(nèi)容較多,戳一戳下方點(diǎn)贊收藏,下次不迷路??~)
一、什么是WebIDE

IDE基本上技術(shù)同學(xué)每天都會(huì)接觸到,比如VS Code就是一個(gè)比較偏向IDE的產(chǎn)品,因?yàn)閂S Code本身內(nèi)置了很多開(kāi)發(fā)功能,還可以通過(guò)插件來(lái)實(shí)現(xiàn)調(diào)試、代碼補(bǔ)全、代碼提示等各類(lèi)功能,借助這些功能就可以比較好的做出一個(gè)集成開(kāi)發(fā)環(huán)境(IDE)。
WebIDE相當(dāng)于IDE產(chǎn)品的Web版。把用戶(hù)界面這一端放到了瀏覽器里面,通過(guò)導(dǎo)航能夠在瀏覽器里面打開(kāi)的,且界面和本地的客戶(hù)端版本幾乎是一樣的。
有一個(gè)WebIDE比較知名的產(chǎn)品是CodeSandBox,同學(xué)寫(xiě)一些demo或者做小的功能需要分享給別人,就會(huì)用類(lèi)似的網(wǎng)站;和它類(lèi)似的還有Codepen,也算是一種WebIDE,它也是把主要界面的操作、交互、開(kāi)發(fā)等放在瀏覽器里面去做的,這是在業(yè)界比較出名的兩個(gè)例子。
接下來(lái)從概念上來(lái)看一下構(gòu)成WebIDE的兩個(gè)部分:Web和IDE。

Web更多是從使用它的產(chǎn)品形態(tài)以及技術(shù)實(shí)現(xiàn)上來(lái)界定的。
與它相對(duì)的是像IDEA這種偏客戶(hù)端的產(chǎn)品。VS Code雖然也是客戶(hù)端產(chǎn)品,但是它本身用了比較多的Web技術(shù)來(lái)構(gòu)建產(chǎn)品的應(yīng)用,里面混合了一些Web技術(shù);CodeSandbox是偏Web端技術(shù)的,是Web端承載的這樣一種產(chǎn)品。那么Web的定義就是在技術(shù)實(shí)現(xiàn)上面去界定的,它也不是兩級(jí)化的,從Desktop到Web我們可以看到它有各種中間狀態(tài),通過(guò)分析哪些組件、哪些部分是如何來(lái)運(yùn)用Web技術(shù),可以讓我們更好地來(lái)分析IDE產(chǎn)品。

IDE是集成開(kāi)發(fā)環(huán)境的縮寫(xiě)。所謂集成開(kāi)發(fā)環(huán)境,包含了平時(shí)會(huì)用的調(diào)試、代碼的高亮、自動(dòng)代碼補(bǔ)全、代碼檢查等;再加上如果做一些面向?qū)ο蟮恼Z(yǔ)言開(kāi)發(fā),還會(huì)看到“類(lèi)”的瀏覽器,以及“類(lèi)”的繼承關(guān)系、相互之間的引用關(guān)系;還有構(gòu)建工具等一些東西集成起來(lái)形成一個(gè)集成開(kāi)發(fā)環(huán)境。
與它更相對(duì)的是一個(gè)偏極端的像Editor這種的編輯器,比如我們可以直接用一個(gè)文本編輯器打開(kāi)一個(gè)代碼模塊,這就是一個(gè)最簡(jiǎn)單的Editor。再比如js這種腳本語(yǔ)言,理論上可以用編輯器直接寫(xiě)代碼,寫(xiě)完之后儲(chǔ)存成js放到網(wǎng)站上運(yùn)行就可以了。
更復(fù)雜的IDE產(chǎn)品比如Android Studio,它不僅包含寫(xiě)代碼和各種預(yù)覽功能,還可能會(huì)包含一些監(jiān)測(cè)應(yīng)用的性能等功能。
所以在IDE的維度上,需要考慮產(chǎn)品功能的完備程度,以及在開(kāi)發(fā)過(guò)程中涉及到的各種功能是否都集成在一個(gè)載體里。集成的越來(lái)越豐富,越能形成一個(gè)集成開(kāi)發(fā)環(huán)境,IDE也就更豐富。
二、WebIDE的一些應(yīng)用場(chǎng)景
以上闡述了 WebIDE的相關(guān)概念。從下圖(圖2-1)也可以看到其實(shí)是有一個(gè)過(guò)渡過(guò)程,每一種產(chǎn)品可能會(huì)位于坐標(biāo)軸的某位置。因?yàn)椴煌a(chǎn)品使用的技術(shù)戰(zhàn)略不同、面向?qū)ο蟛煌蕴幱诓煌恢谩K鼈儾⒉皇且粋€(gè)兩級(jí)對(duì)立的狀態(tài)。

接下來(lái)再聊聊WebIDE的應(yīng)用場(chǎng)景,之前也會(huì)有很多同學(xué)認(rèn)為有了客戶(hù)端的程序來(lái)開(kāi)發(fā)代碼,在本地能開(kāi)發(fā)的東西也很多,那是不是就不需要其他的東西了?這里帶大家看一下業(yè)界有哪些產(chǎn)品以及這些產(chǎn)品是如何去定位的,在它們的場(chǎng)景下做了哪些偏WebIDE方向的事情等。上圖坐標(biāo)軸(圖2-1)代表的是研發(fā)場(chǎng)景的量級(jí)。
輕量級(jí)指的是開(kāi)發(fā)頻次較少,每次開(kāi)發(fā)時(shí)間較短,開(kāi)發(fā)代碼量比較簡(jiǎn)單。比如一個(gè)月開(kāi)發(fā)一兩次左右,每次開(kāi)發(fā)1-1.5個(gè)小時(shí),源碼也不會(huì)出現(xiàn)這種幾十萬(wàn)行的源碼。
重量級(jí)的場(chǎng)景是指每天可能都需要迭代開(kāi)發(fā)一些項(xiàng)目,且源碼量非常巨大,代碼也極其復(fù)雜,整個(gè)開(kāi)發(fā)環(huán)境很龐雜。
所以在整個(gè)坐標(biāo)軸上的不同位置都會(huì)有不同的場(chǎng)景和產(chǎn)品。
(一)輕量級(jí)的應(yīng)用場(chǎng)景
最輕量級(jí)的場(chǎng)景第一個(gè)便是Playground。比如我寫(xiě)了一個(gè)庫(kù),或者像Golang之類(lèi)的各種語(yǔ)言,在推廣給新手運(yùn)用時(shí)會(huì)有一個(gè)Playground,它會(huì)有一個(gè)地方可以直接寫(xiě)代碼片段,然后在旁邊輸出結(jié)果。這實(shí)際上也是一個(gè)非常輕量級(jí)的WebIDE的應(yīng)用場(chǎng)景。
坐標(biāo)軸下面列了一些對(duì)應(yīng)產(chǎn)品,像runkit在NPM會(huì)用到。比如在NPM官網(wǎng)上,每個(gè)包主頁(yè)的右下角應(yīng)該可以看到一個(gè)runkit的按鈕,點(diǎn)擊可以立刻打開(kāi)一個(gè)Playground來(lái)測(cè)試/試用這個(gè)包。
第二個(gè)則是Demo的編寫(xiě)。比如最近新出的一些前端開(kāi)源庫(kù),在它的網(wǎng)站上就會(huì)提供一些輕量級(jí)嵌入的WebIDE,可以直接寫(xiě)代碼,然后用庫(kù)看看效果如何。與之類(lèi)似的還有很多組件庫(kù),傳統(tǒng)的組件庫(kù)肯定是先在頁(yè)面上直接把組件代碼寫(xiě)好,然后基于這段代碼渲染出可交互的組件,讓用戶(hù)能看到。但缺點(diǎn)就是用戶(hù)無(wú)法自主修改調(diào)用代碼,如果想試另一個(gè)API或者參數(shù)值,就無(wú)法調(diào)整。所以更好的方式是能夠直接編輯代碼,以及編輯完之后能直接渲染出如何使用這個(gè)組件,那么用戶(hù)很快能知道組件是否符合要求,以及組件的展示情況是否能夠滿(mǎn)足要求。
比較常用的產(chǎn)品有CodeSandbox。
類(lèi)似輕量級(jí)的還有一些做線(xiàn)上代碼教學(xué)的產(chǎn)品。比如學(xué)一些現(xiàn)成的編程課程,或者是做一些線(xiàn)上的面試時(shí),會(huì)需要寫(xiě)代碼、去運(yùn)行等,這些情況其實(shí)都是比較輕量的。
常用的產(chǎn)品有scrimba,這是一個(gè)比較集成性的產(chǎn)品,它有一些可以交互式的視頻,在看視頻過(guò)程中可以隨時(shí)隨地點(diǎn)到視頻里面去編輯代碼,編輯完代碼運(yùn)行后,還可以繼續(xù)回來(lái)補(bǔ)看。
還有一個(gè)replit,能夠?qū)懜鞣N語(yǔ)言的代碼,然后在線(xiàn)上直接執(zhí)行,還可以做一些教學(xué)等。
(二)偏中型的應(yīng)用場(chǎng)景
偏中型的開(kāi)發(fā)場(chǎng)景一個(gè)是靜態(tài)文檔開(kāi)發(fā)站。我們現(xiàn)在常用的是用沒(méi)有plus的、稍輕些的靜態(tài)文檔工具來(lái)開(kāi)發(fā)。
實(shí)際寫(xiě)代碼時(shí)(不是所謂的頁(yè)面代碼),比如markdown類(lèi)的,再結(jié)合開(kāi)發(fā)一些小的自定義組件,這樣的一個(gè)靜態(tài)站點(diǎn)就出來(lái)了。這個(gè)開(kāi)發(fā)頻率不會(huì)特別高,也不用寫(xiě)太復(fù)雜的代碼,包括幾個(gè)組件或有Markdown的文案就可以。
對(duì)應(yīng)的產(chǎn)品有Nextjs Live和Nextjs Web,Nextjs Web也是應(yīng)用了WebIDE的形態(tài),但是和我們一般看到的編輯器稍有不同,感興趣的同學(xué)可以去深入了解。
還有一個(gè)也稍微輕量級(jí)的場(chǎng)景—開(kāi)發(fā)組件。開(kāi)發(fā)組件相比于實(shí)際項(xiàng)目,代碼量肯定會(huì)更少,又因?yàn)樗拥膬?nèi)聚,所以場(chǎng)景也更加的限定,工具鏈的復(fù)雜度、環(huán)境的復(fù)雜度等也就會(huì)更加簡(jiǎn)單。
可能只需要集中幾十個(gè)源碼文件,且一個(gè)組件的總代碼量一般也不超過(guò)一兩千行。
還有一些low-code的場(chǎng)景,這也可以算是一個(gè)輕量的WebIDE,只是和我們預(yù)想的通用的WebIDE不太一樣,因?yàn)閘ow-code的編輯后面還會(huì)對(duì)接自己的運(yùn)行時(shí)等,集成開(kāi)發(fā)環(huán)境會(huì)更加的定制性,并不是那種通用代碼開(kāi)發(fā)的。
還有像gitpod也是一個(gè)比較輕量級(jí)的產(chǎn)品。
(三)偏重型的應(yīng)用場(chǎng)景
再偏重一些的場(chǎng)景,例如開(kāi)發(fā)FaaS的項(xiàng)目,有很多云廠(chǎng)商會(huì)提供Web端編輯FaaS函數(shù)的方式,同時(shí)也支持在本地用CLI方式或IDE插件的方式去做。
像autocode,它是一個(gè)完全基于云端環(huán)境、瀏覽環(huán)境的產(chǎn)品,用戶(hù)可以在Web的環(huán)境里去開(kāi)發(fā)部署,并且它圍繞WebIDE把很多的云服務(wù)在這做了整合。
最復(fù)雜的還是我們平常接觸最多的比如在VS Code里面去開(kāi)發(fā)一個(gè)復(fù)雜的完整項(xiàng)目。
以上是關(guān)于應(yīng)用場(chǎng)景的一些介紹,從上圖(圖2-1)坐標(biāo)軸也可以看出,不同的位置都可能有不同的WebIDE實(shí)現(xiàn)。因?yàn)閷?duì)功能要求的側(cè)重點(diǎn)不同、面向的產(chǎn)品及需求場(chǎng)景也不同,所以WebIDE的產(chǎn)品覆蓋度是比較廣的。
三、WebIDE的主要實(shí)現(xiàn)思路與對(duì)比
接下來(lái)看一下現(xiàn)在開(kāi)源社區(qū)里面主要的實(shí)現(xiàn)思路都是怎樣的,以及大家都是怎么做WebIDE。

首先來(lái)看一下上圖(圖3-1),看看界面核心部分也就是WebIDE需要具備哪些能力。比如把上面的導(dǎo)航欄蓋掉,會(huì)發(fā)現(xiàn)下面的部分和本地IDE(Desktop IDE)很類(lèi)似,所以來(lái)看一下這樣一個(gè)IDE需要具備哪些必要的功能。
(一)IDE需要具備的必要功能(以前端為例)
首先第一個(gè)需要有文件系統(tǒng)。
第二部分需要在編輯器非常核心的中部區(qū)域能夠編寫(xiě)代碼。最基礎(chǔ)要有個(gè)編輯器。
第三個(gè)部分是需要能支持依賴(lài)包的安裝。因?yàn)槲覀冊(cè)趯?xiě)前端項(xiàng)目時(shí),應(yīng)該都不會(huì)編寫(xiě)這種在編譯時(shí)、運(yùn)行時(shí)完全不需要第三方依賴(lài)的項(xiàng)目(除非場(chǎng)景極其定制收斂)。像上述(圖2-1)的坐標(biāo)軸右側(cè)偏重型的產(chǎn)品和場(chǎng)景,肯定會(huì)需要依賴(lài)安裝。
第四點(diǎn)在寫(xiě)代碼時(shí)需要做代碼編譯才能運(yùn)行。現(xiàn)在寫(xiě)的代碼都已經(jīng)不是原始的js和css,像是vue模板、jsx;也很少有人直接寫(xiě)css,會(huì)選一個(gè)Less或者Sass等;還要做各種編譯、需要兼容各個(gè)瀏覽器及各種版本。所以現(xiàn)在寫(xiě)的代碼一定要做編譯才能運(yùn)行,因?yàn)閹缀醅F(xiàn)在沒(méi)有項(xiàng)目是直接寫(xiě)純粹的最原始代碼。 需要頁(yè)面預(yù)覽。左側(cè)中間這里(圖3-1)有一個(gè)瀏覽器,可以用來(lái)預(yù)覽現(xiàn)在寫(xiě)到的頁(yè)面,前端希望能夠?qū)懲旰罅⒖炭吹巾?yè)面上的東西和效果。因?yàn)樵诰帉?xiě)復(fù)雜樣式時(shí),可能無(wú)法準(zhǔn)確完全的一步到位,會(huì)需要通過(guò)不斷調(diào)校,所以這也是很關(guān)鍵的一個(gè)部分。 與此相關(guān)的是熱更新。我們現(xiàn)在可能會(huì)有很多種狀態(tài)庫(kù),即使不使用狀態(tài)庫(kù),組件也會(huì)有自己內(nèi)部的狀態(tài),如果頁(yè)面全部reload,就會(huì)造成直接丟失。所以前端標(biāo)配就是能夠做模塊的熱更新,能夠局部刷新某個(gè)模塊,這也是一個(gè)比較標(biāo)配要求。 還有一個(gè)是實(shí)時(shí)性。通過(guò)使用Web技術(shù)來(lái)編輯保存,保存完之后刷新頁(yè)面需要及時(shí),頁(yè)面刷新的實(shí)時(shí)性體驗(yàn)是否流暢這點(diǎn)也是比較重要的。在本地編譯器上編譯過(guò)程可能會(huì)稍微慢些,但客戶(hù)端上的操作還是比較流暢的,體驗(yàn)還是不錯(cuò)的。
(二)業(yè)界內(nèi)WebIDE的實(shí)現(xiàn)思路
下面來(lái)看一下在上述提到的基礎(chǔ)功能上,在業(yè)界的實(shí)現(xiàn)思路上是如何做的。

1、VS Code和Theia
第一個(gè)實(shí)現(xiàn)模式下比較著名的兩個(gè)產(chǎn)品,一個(gè)是左邊(圖3-2)VS Code,另一個(gè)是近幾年稍新一點(diǎn)的Theia產(chǎn)品。這兩個(gè)產(chǎn)品在大體的技術(shù)路線(xiàn)上是類(lèi)似的,且這兩個(gè)產(chǎn)品也都是開(kāi)源的,完全能看到它的源碼。

這里舉例說(shuō)一下Theia這個(gè)產(chǎn)品,它的設(shè)計(jì)和代碼目錄結(jié)構(gòu)是比較清晰的,VS Code相對(duì)會(huì)更加復(fù)雜,拆分設(shè)計(jì)沒(méi)有那么清晰。因?yàn)樽铋_(kāi)始這兩個(gè)產(chǎn)品的定位不太一樣,像Theia可以看到里面都有很多的Package,每個(gè)Package對(duì)應(yīng)一個(gè)具體的功能模塊,且功能模塊里面目錄結(jié)構(gòu)也是很清晰的,它會(huì)有一個(gè)叫Browser或Node的目錄,模塊的層級(jí)劃分是比較清晰的。

整體實(shí)現(xiàn)上,前端部分主要負(fù)責(zé)UI,每一個(gè)模塊會(huì)對(duì)應(yīng)一個(gè)前端的實(shí)現(xiàn)。比如ternimal里有各種彩色加速應(yīng)該如何展示出來(lái)。同時(shí)還會(huì)負(fù)責(zé)一些交互,比如在ternimal輸入的東西如何拿到。中間會(huì)通過(guò)WebSocket的方式做一個(gè)協(xié)議。像Theia的話(huà)就用JSON做了一個(gè)自定義格式的協(xié)議,來(lái)和服務(wù)端通信,讓后端對(duì)應(yīng)的模塊也就是ternimal的Node.js模塊收到對(duì)應(yīng)的執(zhí)行方法。ternimal的后端模塊就會(huì)把輸入的內(nèi)容放到對(duì)應(yīng)進(jìn)行的標(biāo)準(zhǔn)輸入里,把標(biāo)準(zhǔn)輸出取出,再返回給前端來(lái)展示。所以它的層級(jí)劃分是每個(gè)功能模塊,大致分成前端(Browser)和服務(wù)端(Node),中間有一個(gè)標(biāo)準(zhǔn)的協(xié)議來(lái)通信。

所以它的具體實(shí)踐上明顯分為兩層,第一層是上圖(圖3-5)紅框里面的Browser瀏覽器,它主要負(fù)責(zé)Web的UI;第二層的是綠框的Server層,Server會(huì)依托于后端環(huán)境和操作系統(tǒng)環(huán)境。整個(gè)Server為了做資源隔離就把它放在一個(gè)容器里面,相當(dāng)于每次在前端對(duì)應(yīng)打開(kāi)一個(gè)WebIDE,背后就有一個(gè)Container,里面的Server就會(huì)做相關(guān)的事情,所以文件系統(tǒng)實(shí)際在前端主要是展示,最終還是存儲(chǔ)在一個(gè)Container里面。

再來(lái)看代碼編輯器,這是一個(gè)純前端的編輯器,一般不會(huì)直接和后端交互,現(xiàn)在常用的選擇就是三個(gè):Ace、Monaco和CodeMirror6。
Ace是一個(gè)非常老牌的編輯器。已經(jīng)出來(lái)有十幾年了,所以功能不一定特別完備,它的UI樣式也稍微老一些;
Monaco屬于中生代,是VS Code本身用的編輯器,然后后來(lái)把它慢慢獨(dú)立出來(lái)做。這個(gè)東西也是現(xiàn)在做WebIDE,很多人會(huì)去選擇的一個(gè)開(kāi)源的編輯器;
Code Mirror是更新一點(diǎn)的。Code Mirror本身不是一個(gè)特別新的編輯器,也做了也很長(zhǎng)時(shí)間了。但是Code Mirror6它是一個(gè)完全重構(gòu)的新版本,在5的基礎(chǔ)上就幾乎重寫(xiě)了一遍,所以這么一個(gè)新版本算是比較新的編輯器,支持很多新特性。
關(guān)于編輯器這里有一些簡(jiǎn)單的對(duì)比(https://blog.replit.com/code-editors),因?yàn)榫庉嬈鲗儆诒容^高內(nèi)聚低耦合的產(chǎn)品,所以在做WebIDE時(shí),為了快速啟動(dòng),選一個(gè)開(kāi)源的產(chǎn)品會(huì)有比較大幫助的,不會(huì)拉垮整個(gè)WebIDE,且接口也比較簡(jiǎn)潔的。
再下一步是依賴(lài)安裝,它有個(gè)服務(wù)端,通過(guò)一個(gè)通信指令在服務(wù)端把安裝包裝上。代碼編譯運(yùn)行也相似,也是在Server端運(yùn)行,然后Server通過(guò)網(wǎng)絡(luò)協(xié)議和Web里的某一頁(yè)面進(jìn)行通信。由于有實(shí)際的服務(wù)端,所以在這個(gè)架構(gòu)下的頁(yè)面預(yù)覽、熱更新等和本地開(kāi)發(fā)基本是一致的,服務(wù)、編譯等都是在Container里面的。
在實(shí)時(shí)性上主要取決于兩點(diǎn):一是通信是否會(huì)有延遲,是否會(huì)有帶寬問(wèn)題,以及服務(wù)穩(wěn)定性如何;第二點(diǎn)是由于涉及前端編譯運(yùn)行,所以分配的資源是否足夠也會(huì)有影響。
2、CodeSandbox
下面再說(shuō)第二個(gè)實(shí)現(xiàn)思路是CodeSandbox。這個(gè)思路和前面的技術(shù)路線(xiàn)和想法差異比較大,所以需要單獨(dú)介紹一下。

CodeSandbox本身是一個(gè)開(kāi)源的產(chǎn)品,它把客戶(hù)端的IDE部分開(kāi)源出來(lái)了,所以可以直接看到它的源碼,了解它的各種實(shí)現(xiàn)。在它早期發(fā)表的文章上也介紹了一些他們?cè)趯?shí)現(xiàn)WebIDE上面的關(guān)鍵思考點(diǎn)等。雖然技術(shù)實(shí)現(xiàn)細(xì)節(jié)有了非常多的迭代,但是它整體的技術(shù)思路大致是這個(gè)方向。

上圖(圖3-7)Code Sandbox的圖,可以看到右邊這個(gè)圖上看出,它沒(méi)有像VS Code或Theia分Broswer或Server,因?yàn)檫@些部分全都在 Broswer里,所以它的文件系統(tǒng)是一個(gè)基于瀏覽器內(nèi)存的文件系統(tǒng)。編輯器這塊在技術(shù)路線(xiàn)上沒(méi)有太大的差異,都是直接用開(kāi)源的產(chǎn)品。
在依賴(lài)安裝這部分和前兩者也有很大不同,因?yàn)樗鼪](méi)有一個(gè)服務(wù)端環(huán)境,意味著它不能用“正常”的方式安裝,同時(shí)因?yàn)樗且粋€(gè)基于瀏覽器內(nèi)存的文件系統(tǒng),所以即使在某個(gè)server安裝上這些東西,也需要它搬到瀏覽器里面來(lái),然后把它放到這個(gè)文件系統(tǒng)上去才行。所以在這里有一個(gè)服務(wù)(圖3-7最右側(cè)),專(zhuān)門(mén)來(lái)處理NPM包,把NPM包代碼處理完后直接給前端瀏覽器返回,再通過(guò)接口的方式返回NPM包里面文件內(nèi)容以及一些其他信息等。
通過(guò)這個(gè)轉(zhuǎn)換服務(wù),在左側(cè)這里(上圖3-7)去搜一個(gè)React時(shí)可以把React的版本列出來(lái),在下拉框里選中目標(biāo)后就會(huì)通過(guò)這個(gè)服務(wù),把所有依賴(lài)的NPM包里面的代碼內(nèi)容返回到前端,然后前端把它裝載到文件系統(tǒng)里面,這樣就可以去做依賴(lài)安裝。
下一塊代碼的編譯運(yùn)行主要關(guān)注綠色這部分(圖3-8),這也是重度開(kāi)發(fā)的部分。代碼編譯會(huì)基于開(kāi)源工具(babel、vue compiler等)來(lái)手寫(xiě)一個(gè)可在瀏覽器內(nèi)運(yùn)行的打包器。運(yùn)行則會(huì)依托于iframe,把代碼放到iframe里面讓它去運(yùn)行和渲染頁(yè)面。
關(guān)于頁(yè)面預(yù)覽,iframe并不是真正的去某一個(gè)服務(wù)端把資源加載進(jìn)來(lái),它通過(guò)前端的方式,可以是 Service Worker 直接攔截返回,或者直接通過(guò)前端的通信機(jī)制發(fā)送代碼來(lái)加載。熱更新這部分的話(huà),肯定需要自己做一些熱更新的這種操作,因?yàn)樗前压ぞ哝溸@塊自己接管的。
實(shí)時(shí)性上一般沒(méi)有太大差別,上面可以看到它是一個(gè)純?yōu)g覽器內(nèi)部的操作,瀏覽器主線(xiàn)程會(huì)頻繁和web worker進(jìn)行各種通信,所以相比較要去和服務(wù)端通信,它的時(shí)間可能會(huì)要稍微短一點(diǎn)。
這節(jié)的最后給這兩種模式做個(gè)簡(jiǎn)單對(duì)比(圖3-9):

Theia的模式由于需要有服務(wù)端的實(shí)現(xiàn),所以在資源開(kāi)銷(xiāo)和運(yùn)維成本上有劣勢(shì);而CodeSandbox由于需要自研工具鏈,所以在前端這個(gè)新框架迭代頻繁的領(lǐng)域有較大開(kāi)發(fā)成本,同時(shí)由于缺乏服務(wù)端能力,能滿(mǎn)足的場(chǎng)景也有限,主要還是純前端的代碼編譯。
四、WebContainer思路下的WebIDE
最后來(lái)說(shuō)一下 WebContainer的思路下是如何做IDE的。WebContainer是stackblitz公司提出的一種技術(shù)模式,算是第三種模式。目前社區(qū)沒(méi)有開(kāi)源實(shí)現(xiàn),因?yàn)檫@個(gè)是比較核心的技術(shù),所以做這個(gè)的stackblitz公司也沒(méi)有在公開(kāi)的資料里說(shuō)過(guò)具體的技術(shù)細(xì)節(jié),只有一些概念。
可以體驗(yàn)下(https://stackblitz.com/),實(shí)現(xiàn)原理大致是利用了wasm的特性,將node相關(guān)代碼進(jìn)行轉(zhuǎn)換為在瀏覽器work可以執(zhí)行的wasm代碼,這樣在瀏覽器就支持了node的運(yùn)行。
WebContainer的核心目標(biāo)是,既想跑服務(wù)端代碼(跟VS Code一樣),但又不想有服務(wù)端容器。

它在這里提了一個(gè)概念,把服務(wù)端代碼運(yùn)行在一個(gè)所謂的WebContainer里,這個(gè)WebContainer是完全運(yùn)行在瀏覽器里的,這樣就做到了類(lèi)似這樣一種架構(gòu)。

這種架構(gòu)和Theia對(duì)比層級(jí)結(jié)構(gòu)很像。Web UI這邊可以說(shuō)大致類(lèi)似,層級(jí)圖的下面這部分,在Theia里面是完整跑在服務(wù)端的Node.js的環(huán)境里的,而在WebContainer 這樣的實(shí)現(xiàn)下面,就要跑在瀏覽器里面(圖4-2)。由于前端相關(guān)的服務(wù)端應(yīng)用基本都依賴(lài)Node.js,所以這里非常重要的一個(gè)問(wèn)題就是怎樣讓Node.js程序能夠跑在瀏覽器里面?如果把Node.js跑到瀏覽器的問(wèn)題解決,就解決了很大一部分的技術(shù)問(wèn)題。各種Node.js代碼、應(yīng)用、各種NPM包、構(gòu)建工具就可以直接跑在瀏覽器里面,之前需要一個(gè)Server環(huán)境來(lái)做,現(xiàn)在就不需要了。所以在這樣一個(gè)思路下,就可以把server搬到瀏覽器里面來(lái)做。
它和CodeSandbox不一樣,CodeSandbox在綠色部分(圖4-2)也就是在Web woker的技術(shù)上做了各類(lèi)技術(shù)棧的構(gòu)建工具鏈,NPM也需要去單獨(dú)做處理。
這個(gè)對(duì)比可以看到二者實(shí)現(xiàn)的事情和層級(jí)上是不同的。理論上基于WebContainer的方式NPM也不需要再單獨(dú)處理。如果實(shí)現(xiàn)了完整的Node.js運(yùn)行環(huán)境,可以把npm install拋到worker里面去,但是可能會(huì)有一些性能和效率的問(wèn)題。所以做 WebIDE需要定制一個(gè)在瀏覽器里面能夠獨(dú)立運(yùn)行NPM CLI工具。
這里要涉及三點(diǎn):第一個(gè)是依賴(lài)的解析;第二個(gè)是怎么去把包拉下來(lái);最后是拉到之后你需要去解包解壓。
基于WebContainer模式下的WebIDE能夠較好規(guī)避前兩個(gè)模式的缺點(diǎn)(圖4-4):

由于所謂的server也運(yùn)行在瀏覽器中,所以資源消耗和運(yùn)維成本就降為0,安全隔離也不需要docker container這種技術(shù),瀏覽器自帶了沙箱特性。同時(shí)由于模擬了Node.js運(yùn)行環(huán)境和基礎(chǔ)的shell能力,所以在工具鏈上可以大量服用前端已有工具包,無(wú)需定制開(kāi)發(fā)工具鏈。
最后總結(jié)一下,基于WebContainer的WebIDE在整個(gè)應(yīng)用場(chǎng)景從輕到重上來(lái)說(shuō),屬于是一個(gè)它可以處理從輕到重的產(chǎn)品。在輕量級(jí)場(chǎng)景下,我們可以用它做playgroud,做demo編寫(xiě),都是可以的。然后再偏中量級(jí)上面的話(huà),可以在它上面運(yùn)行vuepress或者vitepress(Vue團(tuán)隊(duì)做的工具)來(lái)進(jìn)行靜態(tài)的站點(diǎn)搭建,你可以在這上面直接去開(kāi)發(fā)你的靜態(tài)站然后聯(lián)通部署服務(wù)。
現(xiàn)在我們是做了一個(gè)產(chǎn)品(暫不對(duì)外開(kāi)放),可以進(jìn)行一些在線(xiàn)Demo的編寫(xiě)、分享,除了運(yùn)行純前端組件、包之外,也可以運(yùn)行一些命令行工具、或者Node.js包。隨著開(kāi)發(fā)體驗(yàn)與周邊工具(例如git)的補(bǔ)齊,它這種技術(shù)模式在這個(gè)場(chǎng)景軸上,所能覆蓋范圍會(huì)更長(zhǎng)一些。然后本身它內(nèi)部的各個(gè)子模塊也可以獨(dú)立輸出出來(lái),像最近CodeSandbox它其實(shí)也有意把自己的Sandbox給摳出來(lái),獨(dú)立出來(lái)做一個(gè)輕量級(jí)的輸出,就不整個(gè)輸出WebIDE這塊東西。
(下方???? 為文章中提到的技術(shù)產(chǎn)品和文檔鏈接,感興趣的同學(xué)可點(diǎn)擊查閱~)
https://blog.replit.com/code-editors
https://github.com/codesandbox
https://codesandbox.io/post/creating-a-parallel-offline-extensible-browser-based-bundler-for-codesandbox
https://codesandbox.io/post/how-we-make-npm-packages-work-in-the-browser
https://codesandbox.io/post/sandpack-announcement
https://codesandbox.io/docs/environment#container-environment
https://codesandbox.io/post/announcing-codesandbox-containers
https://stackblitz.com/
