一亮蛔、什么是微前端尔邓?
微前端一詞第一次出現(xiàn)是在工作思維(ThoughtWorks)2016年的技術(shù)雷達(dá)( Technology Radar )中。微前端是一種架構(gòu)齿尽,是將整個(gè)巨石應(yīng)用拆分成多個(gè)可獨(dú)立開發(fā)灯节、部署、上線卡骂,運(yùn)行的小型應(yīng)用(子應(yīng)用)全跨,對(duì)外暴露一個(gè)控制臺(tái)應(yīng)用(父應(yīng)用)來(lái)統(tǒng)一管理各個(gè)子應(yīng)用的運(yùn)行狀態(tài)浓若,多個(gè)子應(yīng)用間在用戶無(wú)感情況下往復(fù)切換。
現(xiàn)代應(yīng)用痛點(diǎn):
- 項(xiàng)目中的組件和功能模塊會(huì)越來(lái)越多是越,導(dǎo)致整個(gè)項(xiàng)目的打包速度變慢碌上;
- 因?yàn)槲募A的數(shù)量會(huì)隨著功能模塊的增多而增多,查找代碼會(huì)變得越來(lái)越慢馏予;
- 如果只改動(dòng)其中一個(gè)模塊的情況天梧,需要把整個(gè)項(xiàng)目重新打包上線;
- 目錄層級(jí)和模塊層級(jí)過(guò)深而且文件又多吗蚌,定位文件會(huì)越來(lái)越慢腿倚;
- 所有的項(xiàng)目都只能使用同一技術(shù)框架如:react、vue等蚯妇;
微前端的優(yōu)勢(shì)
- 無(wú)技術(shù)棧限制:主框架不限制接入應(yīng)用的技術(shù)棧,子應(yīng)用具備完全自主權(quán)
- 獨(dú)立開發(fā)暂筝,獨(dú)立部署箩言,子應(yīng)用的倉(cāng)庫(kù)獨(dú)立,前后端可獨(dú)立進(jìn)行開發(fā)焕襟,部署完成后主框架自動(dòng)完成同步更新
- 獨(dú)立運(yùn)行:每個(gè)項(xiàng)目都可以作為一個(gè)完整的單獨(dú)項(xiàng)目去運(yùn)行。獨(dú)立運(yùn)行時(shí)鸵赖,每個(gè)子應(yīng)用之間狀態(tài)隔離务漩,運(yùn)行時(shí)狀態(tài)不共享
二、微前端架構(gòu)解決方案
- 2018 single-spa 是一個(gè)用于前端微服務(wù)化的 javascript 前端解決方案它褪,(本身沒(méi)有處理樣式隔離饵骨,js 執(zhí)行隔離)實(shí)現(xiàn)了路由的劫持和應(yīng)用加載;
- 2019 qiankun 基于 single-spa 提供了更加開箱即用的 api(single-spa+sandbox+import-html-entry)做到了茫打,技術(shù)棧無(wú)關(guān)居触,并且接入簡(jiǎn)單妖混。
三、single-spa
解決的問(wèn)題
single-spa 實(shí)現(xiàn)了路由劫持和應(yīng)用加載的功能: 監(jiān)聽(tīng)路由加載子模塊
Single-spa 是一個(gè)將多個(gè)單頁(yè)面應(yīng)用聚合為一個(gè)整體應(yīng)用的 JavaScript 微前端框架轮洋。
基座提供注冊(cè)邏輯制市、子應(yīng)用提供三個(gè)協(xié)議接入方法和打包格式
子應(yīng)用可以獨(dú)立部署,運(yùn)行時(shí)動(dòng)態(tài)加載主子應(yīng)用完全解耦弊予,技術(shù)棧無(wú)關(guān)祥楣,靠的是協(xié)議接入(子應(yīng)用必須導(dǎo)出 bootstrap,mount汉柒,unmount 方法)
基座
在基座里我們調(diào)用single-spa提供給我們的registerApplication和start的方法
singleSpa.registerApplication:這是注冊(cè)子項(xiàng)目的方法误褪。參數(shù)如下:
appName: 子項(xiàng)目名稱
applicationOrLoadingFn: 子項(xiàng)目注冊(cè)函數(shù),用戶需要返回 single-spa 的生命周期對(duì)象竭翠。后面我們會(huì)介紹single-spa的生命周期機(jī)制
activityFn: 回調(diào)函數(shù)入?yún)?location 對(duì)象振坚,可以寫自定義匹配路由加載規(guī)則。
singleSpa.start:這是啟動(dòng)函數(shù)斋扰。
注意:父項(xiàng)目的 vue-router 要開啟history模式渡八。
子項(xiàng)目
如果想注冊(cè)為一個(gè)子項(xiàng)目,還需要 single-spa-vue 的包裝传货。
在main.js中引入 single-spa-vue屎鳍,傳入Vue對(duì)象和vue.js掛載參數(shù),就可以實(shí)現(xiàn)注冊(cè)问裕。它會(huì)返回一個(gè)對(duì)象逮壁,里面有single-spa 需要的生命周期函數(shù)。使用export導(dǎo)出即可粮宛。
子項(xiàng)目最重要的就是提供三個(gè)方法 bootstrap窥淆、mount、unmount 和 打包格式
import singleSpaVue from "single-spa-vue";
import Vue from 'vue'
const vueOptions = {
el: "#microApp",
router,
store,
render: h => h(App)
};
// singleSpaVue包裝一個(gè)vue微前端服務(wù)對(duì)象
const vueLifecycles = singleSpaVue({
Vue,
appOptions: vueOptions
});
// 導(dǎo)出生命周期對(duì)象
export const bootstrap = vueLifecycles.bootstrap; // 啟動(dòng)時(shí)
export const mount = vueLifecycles.mount; // 掛載時(shí)
export const unmount = vueLifecycles.unmount; // 卸載時(shí)
webpack的處理
只是導(dǎo)出了巍杈,還需要掛載到window忧饭。
在項(xiàng)目目錄下新建 vue.config.js, 修改我們的webpack配置。我們修改webpack output內(nèi)的 library 和 libraryTarget 字段筷畦。
output.library: 導(dǎo)出的對(duì)象名
output.libraryTarget: 導(dǎo)出后要掛載到哪里
同時(shí)词裤,因?yàn)槲覀兪沁h(yuǎn)程調(diào)用,還需要設(shè)置 publicPath 字段為你的真實(shí)服務(wù)地址鳖宾。否則加載子chunk時(shí)吼砂,會(huì)去當(dāng)前瀏覽器域名的根路徑尋找,有404問(wèn)題鼎文。
因?yàn)槲覀儽镜氐姆?wù)啟動(dòng)是localhost:3000渔肩,所以我們就設(shè)置 //localhost:3000。
獨(dú)立運(yùn)行
我們的子服務(wù)現(xiàn)在是無(wú)法獨(dú)立運(yùn)行的漂问,現(xiàn)在我們改造為可以獨(dú)立 + 集成雙模式運(yùn)行
single-spa 有個(gè)屬性赖瞒,叫做 window.singleSpaNavigate女揭。如果為true,代表就是single-spa模式栏饮。如果false吧兔,就可以獨(dú)立渲染。
改造一下子項(xiàng)目的main.js :
/**** 添加這里 ****/
if (!window.singleSpaNavigate) { // 如果不是single-spa模式
delete vueOptions.el;
new Vue(vueOptions).$mount('#app');
}
這樣袍嬉,我們就可以獨(dú)立訪問(wèn)子服務(wù)的 index.html
使用 single-spa 進(jìn)行前端架構(gòu)設(shè)計(jì)可以帶來(lái)很多好處:
例如:
在同一頁(yè)面上使用多個(gè)前端框架而不用刷新頁(yè)面] (react境蔼,vue等 )
獨(dú)立部署每一個(gè)單頁(yè)面應(yīng)用
新功能使用新框架,舊的單頁(yè)應(yīng)用不用重寫可以共存
改善初始加載時(shí)間伺通,延遲加載代碼
缺點(diǎn):
- 在上面父項(xiàng)目加載子項(xiàng)目的代碼中箍土,我們可以看到。我們要注冊(cè)一個(gè)子服務(wù)罐监,需要一次性加載2個(gè)JS文件吴藻。如果需要加載的JS更多,甚至生產(chǎn)環(huán)境的 bundle 有唯一hash弓柱, 那我們還能寫死文件名和列表嗎沟堡?
- 侵入性太強(qiáng),不僅要在入口導(dǎo)出生命周期矢空,還要更改 Webpack 配置
JS Entry 的接入微應(yīng)用方式來(lái)簡(jiǎn)陋了航罗,我們更希望是通過(guò)一個(gè) index.html 的 url 來(lái)接入微應(yīng)用
啥都沒(méi)有,比如 JS屁药、CSS 隔離粥血,主微應(yīng)用通信等這些都需要?jiǎng)e的小庫(kù)來(lái)解決