MicroApp是由京東前端團隊推出的一款微前端框架,它從元件化的思維,基於類WebComponent進行微前端的渲染,旨在降低上手難度、提升工作效率。MicroApp無關技術棧,也不和業務繫結,可以用於任何前端框架。
微前端是一種頁面整合方案,它的核心在於將一個龐大的前端應用拆分成多個獨立靈活的小型應用,每個應用都可以獨立開發、獨立執行、獨立部署,再將這些小型應用融合為一個完整的應用,或者將原本執行已久、沒有關聯的幾個應用融合為一個應用。微前端既可以將多個專案融合為一,又可以減少專案之間的耦合,提升專案擴充套件性,相比一整塊的前端倉庫,微前端架構下的前端倉庫傾向於更小更靈活。
距離MicroApp開源已經有一年多時間,在這段時間裡我們收到了很多問題反饋,包括沙箱的效能、vite的相容、路由衝突等等,為了解決這些問題我們將很多核心功能進行升級和重構,經過不斷的打磨和驗證,最終推出MicroApp1.0正式版。
正式版的升級主要在以下幾個方面:
更簡潔的接入方式
沙箱的效能
虛擬路由系統
樣式隔離
相容vite
開發工具
MicroApp借鑑了WebComponent的思想,通過CustomElement結合自定義的ShadowDom,將微前端封裝成一個類WebComponent元件,實現微前端的元件化渲染。在此基礎上,通過實現JS隔離、樣式隔離、路由隔離,降低子應用的接入成本,子應用只需設定允許跨域請求,不需要改動任何程式碼即可接入微前端,使用方式和iframe幾乎一致,但卻沒有iframe存在的問題。
接入方式如下:
在MicroApp開源後我們收到社群的一些反饋,其中一條關於效能的問題引起我們的重視。這不是MicroApp才存在的問題,而是微前端長久以來的難題,在社群有大量關於沙箱效能問題的討論,卻始終沒有完美的解決方案。
MicroApp採用的是和qiankun一樣的proxy+with的沙箱方案,這也是目前js沙箱的主流方案 。with沙箱的功能非常完善,但是效能損耗卻非常明顯,在社群中也不乏對with沙箱效能問題的討論,但一直沒有特別完美的解決方案,這是由於with改變了js的作用域鏈,從而產生大量的重複請求。問題的根源是with,但又不全是with的問題,準確的說是with和proxy兩者疊加造成的,with和proxy本質上的效能都不高,需要一種方案避免對這兩個方法的頻繁讀取操作,MicroApp採用的解決方案是變數前置和非同步防抖。
• 變數前置:是指使用Object.defineProperty定義全域性變數,通過get和set設定響應資料,一是為了避免在proxy的get中進行多餘的操作,二是defineProperty的效能比proxy更優秀 。
• 非同步防抖:是指在子應用執行時對promise進行標記,確保在上一個promise執行完成之後才會進入下一個,避免並行觸發,防止promise被頻繁觸發會造成效能損失。
在此基礎上,MicroApp沙箱還提供了快照、快取、預載入等功能,在保證功能不變的前提下,徹底解決沙箱的效能問題,升級後的沙箱執行效率媲美原生JS。
微前端是將多個不同的web應用融合在一起渲染,但瀏覽器只有一個路由系統,這很容易造成應用之間的路由衝突,最常見的就是vue3的路由衝突問題。
上面是vue-router作者對於在微前端環境下的衝突問題的回答,他認為vue-router已經覆蓋足夠多場景,微前端的問題應該由微前端解決。
在我們剛開源時,並沒有對路由進行隔離,使用者對於MicroApp的問題幾乎一半都和路由相關,因為一個路由系統同時滿足多個應用的渲染容易導致衝突,也非常反直覺和難以理解,於是我們推出了虛擬路由系統。
概念圖:
虛擬路由系統與瀏覽器的路由行為一致,它通過自定義location和history等核心路由API,重寫了popState和hashChange事件,攔截路由導航和事件,並提供了一系列自定義API,模擬了在瀏覽器環境下的Web應用程式的渲染、跳轉和返回等路由行為。子應用程式在這個虛擬路由系統中執行,與基座應用程式的路由相互隔離,從而避免相互影響,並增強了子應用程式與基座應用程式之間的互動能力。通過虛擬路由系統,基座應用程式可以方便地獲取子應用程式的路由資訊並控制子應用程式的跳轉,子應用程式的路由資訊會作為引數同步到瀏覽器地址上。此外,虛擬路由系統還提供了許多功能,幫助開發人員提高工作效率。
MicroApp最初是基於style元素的CSSStyleSheet實現的樣式隔離:即將CSS字串插入style元素生成CSSStyleSheet,遍歷每個CSS規則,新增字首實現樣式隔離。
這種一種取巧的方式,利用瀏覽器自身的能力格式化CSS,並在此基礎上進行修改,省去很多工作量。但問題也出現在這裡,不同瀏覽器對於相同的CSS生成的CSSStyleSheet可能會不同,這就導致我們在處理CSSStyleSheet會遇到不可以預知的問題,導致CSS表現不一致。
於是MicroApp換了一種方式來實現樣式隔離,我們使用正則將CSS字串切割成最小單元,每個單元包含一段CSS資訊,將所有的資訊整理生成CSSTree,遍歷CSSTree的每個規則,新增字首實現樣式隔離。
新的方案不但抹平了不同平臺間的差異,在效能上相較於舊版普遍提升30%以上,並且擁有更加靈活的設定:
/* 對指定的選擇器禁用樣式隔離 *
/*! scopecss-disable .test1, .test2 */
.test1 {
color: red;
}
.test2 {
color: yellow;
}
.test3 {
/* 在某一行中禁用樣式隔離 */
/*! scopecss-disable-next-line */
background: url(/test.png);
}
在之前的版本中,MicroApp也支援vite的接入,但必須關閉沙箱,因為vite打包出來的是esm型別的js檔案,而esm無法執行在with環境中,但這樣容易導致基座和子應用之間的衝突,顯然是需要進一步優化的。
為此我們為vite(更準確的說是為esm型別的專案)開發了一套iframe沙箱方案,將esm型別的js檔案放入iframe中執行,並通過重寫子應用底層原型鏈的方式,實現對js和元素的攔截和處理。
iframe沙箱和with沙箱的實現方式不同,功能也略有不同,with沙箱擁有更加靈活的操作,而iframe沙箱擁有更加嚴格的隔離環境,兩者各有優劣。使用者可以在兩種沙箱之間靈活切換,以滿足更多特殊場景的覆蓋和相容。
Micro-App-DevTools 是基於 MicroApp 推出的一款Chrome瀏覽器外掛,目的是為了在開發和使用 MicroApp 過程中提高效率。通過此外掛可以有效的解決偵錯困難、模擬資料通訊、檢視視窗範圍、設定路由、獲取環境變數等訴求,進而更好地幫助使用者去了解和使用 MicroApp。
Micro-App-DevTools通過模擬子應用開發環境,獲取父應用資料,來視覺化檢視通訊資料,提高開發偵錯效率。對於路由,將會顯示所有應用的路由,包含層層巢狀應用以及一個父應用多個子應用的路由,使不同團隊應用也能快速定位自己問題,方便共同作業。還提供了全域性變數和高亮視窗功能,實現快速定位範圍,提高排查效率的功能,並集結了圖示、右鍵、控制檯的快捷進入方式,使使用者快速上手,零成本使用。
MicroApp 1.0已經發布,我們將積極迴應開發者的問題和反饋,並持續改進,以幫助更多開發者提高效率和改善開發體驗。歡迎大家使用MicroApp並參與共建,也希望在GitHub上給我們點個Star來支援我們~
MicroApp Github地址:
https://github.com/micro-zoe/micro-app
Micro-App-DevTools Github地址:
https://github.com/micro-zoe/micro-app-chrome-plugin
MicroApp官網地址:
https://micro-zoe.github.io/micro-app
作者:京東零售 馬國華
來源:京東雲開發者社群 轉載請註明來源