【微前端】1228- Vite 微前端實踐,實現(xiàn)一個組件化的方案
微前端是一種多個團隊通過獨立發(fā)布功能的方式來共同構(gòu)建現(xiàn)代化 web 應(yīng)用的技術(shù)手段及方法策略。
微前端借鑒了微服務(wù)的架構(gòu)理念,將一個龐大的前端應(yīng)用拆分為多個獨立靈活的小型應(yīng)用,每個應(yīng)用都可以獨立開發(fā)、獨立運行、獨立部署,再將這些小型應(yīng)用聯(lián)合為一個完整的應(yīng)用。微前端既可以將多個項目融合為一,又可以減少項目之間的耦合,提升項目擴展性,相比一整塊的前端倉庫,微前端架構(gòu)下的前端倉庫傾向于更小更靈活。
特性
技術(shù)棧無關(guān) 主框架不限制接入應(yīng)用的技術(shù)棧,子應(yīng)用可自主選擇技術(shù)棧 獨立開發(fā)/部署 各個團隊之間倉庫獨立,單獨部署,互不依賴 增量升級 當(dāng)一個應(yīng)用龐大之后,技術(shù)升級或重構(gòu)相當(dāng)麻煩,而微應(yīng)用具備漸進式升級的特性 獨立運行時 微應(yīng)用之間運行時互不依賴,有獨立的狀態(tài)管理 提升效率 應(yīng)用越龐大,越難以維護,協(xié)作效率越低下。微應(yīng)用可以很好拆分,提升效率
目前可用的微前端方案
微前端的方案目前有以下幾種類型:
基于 iframe 完全隔離的方案
作為前端開發(fā),我們對 iframe 已經(jīng)非常熟悉了,在一個應(yīng)用中可以獨立運行另一個應(yīng)用。它具有顯著的優(yōu)點:
非常簡單,無需任何改造 完美隔離,JS、CSS 都是獨立的運行環(huán)境 不限制使用,頁面上可以放多個 iframe來組合業(yè)務(wù)
當(dāng)然,缺點也非常突出:
無法保持路由狀態(tài),刷新后路由狀態(tài)就丟失 完全的隔離導(dǎo)致與子應(yīng)用的交互變得極其困難 iframe中的彈窗無法突破其本身整個應(yīng)用全量資源加載,加載太慢
這些顯著的缺點也催生了其他方案的產(chǎn)生。
基于 single-spa 路由劫持方案
single-spa 通過劫持路由的方式來做子應(yīng)用之間的切換,但接入方式需要融合自身的路由,有一定的局限性。
qiankun 孵化自螞蟻金融科技基于微前端架構(gòu)的云產(chǎn)品統(tǒng)一接入平臺。它對 single-spa 做了一層封裝。主要解決了 single-spa 的一些痛點和不足。通過 import-html-entry 包解析 HTML 獲取資源路徑,然后對資源進行解析、加載。
通過對執(zhí)行環(huán)境的修改,它實現(xiàn)了 JS 沙箱、樣式隔離 等特性。
京東 micro-app 方案
京東 micro-app 并沒有沿襲 single-spa 的思路,而是借鑒了 WebComponent 的思想,通過 CustomElement 結(jié)合自定義的 ShadowDom,將微前端封裝成一個類 webComponents 組件,從而實現(xiàn)微前端的組件化渲染。
在 Vite 上使用微前端
我們從 我們從 UmiJS 遷移到了 Vite 之后,微前端也成為了勢在必行,當(dāng)時也調(diào)研了很多方案。
為什么沒用 qiankun
qiankun 是目前是社區(qū)主流微前端方案。它雖然很完善、流行,但最大的問題就是不支持 Vite。它基于 import-html-entry 解析 HTML 來獲取資源,由于 qiankun 是通過 eval 來執(zhí)行這些 js 的內(nèi)容,而 Vite 中的 script 標(biāo)簽類型是 type="module",里面包含 import/export 等模塊代碼, 所以會報錯:不允許在非 type="module" 的 script 里面使用 import。
退一步實現(xiàn),我們采用了 single-spa 的方式,并使用 systemjs 的方式進行了微前端加載方案,也踩了不少的坑。single-spa 沒有一個友好的教程來接入,文檔雖然多,但大多都在講概念,當(dāng)時讓人覺得有一種深奧的感覺。
后來看了它的源碼發(fā)現(xiàn),這都是些什么……里面大部分代碼都是圍繞路由劫持而展開的,根本沒有文檔上那種高大上的感覺。而我們又用不到它路由劫持的功能,那我們?yōu)槭裁匆盟?/p>
從組件化的層面來說 single-spa 這種方式實現(xiàn)得一點都不優(yōu)雅。
它劫持了路由,與 react-router和組件化的思維格格不入接入方式一大堆繁雜的配置 單實例的方案,即同一時刻,只有一個子應(yīng)用被展示
后來琢磨著 single-spa 的缺點,我們可以自己實現(xiàn)一個組件化的微前端方案。
如何實現(xiàn)一個簡單、透明、組件化的方案
通過組件化思維實現(xiàn)一個微應(yīng)用非常簡單:子應(yīng)用導(dǎo)出一個方法,主應(yīng)用加載子應(yīng)用并調(diào)用該方法,并傳入一個 Element 節(jié)點參數(shù),子應(yīng)用得到該 Element 節(jié)點,將本身的組件 appendChild 到 Element 節(jié)點上。

類型約定
在此之前我們需要約定一個主應(yīng)用與子應(yīng)用之間的一個交互方式。主要通過三個鉤子來保證應(yīng)用的正確執(zhí)行、更新、和卸載。
類型定義:
export interface AppConfig {
// 掛載
mount?: (props: unknown) => void;
// 更新
render?: (props: unknown) => ReactNode | void;
// 卸載
unmount?: () => void;
}
子應(yīng)用導(dǎo)出
通過類型的約定,我們可以將子應(yīng)用導(dǎo)出:mount、render、unmount 為主要鉤子。
React 子應(yīng)用實現(xiàn):
export default (container: HTMLElement) => {
let handleRender: (props: AppProps) => void;
// 包裹一個新的組件,用作更新處理
function Main(props: AppProps) {
const [state, setState] = React.useState(props);
// 將 setState 方法提取給 render 函數(shù)調(diào)用,保持父子應(yīng)用觸發(fā)更新
handleRender = setState;
return <App {...state} />;
}
return {
mount(props: AppProps) {
ReactDOM.render(<Main {...props} />, container);
},
render(props: AppProps) {
handleRender?.(props);
},
unmount() {
ReactDOM.unmountComponentAtNode(container);
},
};
};
Vue 子應(yīng)用實現(xiàn):
import { createApp } from 'vue';
import App from './App.vue';
export default (container: HTMLElement) => {
// 創(chuàng)建
const app = createApp(App);
return {
mount() {
// 裝載
app.mount(container);
},
unmount() {
// 卸載
app.unmount();
},
};
};
主應(yīng)用實現(xiàn)
React 實現(xiàn)
其核心代碼僅十余行,主要處理與子應(yīng)用交互 (為了易讀性,隱藏了錯誤處理代碼):
export function MicroApp({ entry, ...props }: MicroAppProps) {
// 傳遞給子應(yīng)用的節(jié)點
const containerRef = useRef(null);
// 子應(yīng)用配置
const configRef = useRef();
useLayoutEffect(() => {
import(/* @vite-ignore */ entry).then((res) => {
// 將 div 傳給子應(yīng)用渲染
const config = res.default(containerRef.current);
// 調(diào)用子應(yīng)用的裝載方法
config.mount?.(props);
configRef.current = config;
});
return () => {
// 調(diào)用子應(yīng)用的卸載方法
configRef.current?.unmount?.();
configRef.current = undefined;
};
}, [entry]);
return <div ref={containerRef}>{configRef.current?.render?.(props)}div>;
}
完成,現(xiàn)在已經(jīng)實現(xiàn)了主應(yīng)用與子應(yīng)用的裝載、更新、卸載的操作。現(xiàn)在,它是一個組件,可以同時渲染出多個不同的子應(yīng)用,這點就比 single-spa 優(yōu)雅很多。
entry 子應(yīng)用地址,當(dāng)然真實情況會根據(jù) dev 和 prod 模式給出不同的地址:
"micro-app" entry="http://localhost:3002/src/main.tsx" />
Vue 實現(xiàn)
青青草污视频
|
国产777在线
|
在线做爱|
在线手机av|
91蜜桃婷婷狠狠久久综合
|
