微前端架構(gòu)下娜汁,主應(yīng)用有自己的路由模塊,同時主應(yīng)用支持以微前端的方式嵌入業(yè)務(wù)模塊(子應(yīng)用),如何實現(xiàn)呢仁锯?
關(guān)于路由
qiankun
在主應(yīng)用初始化會自動監(jiān)聽路由的變化去匹配注冊好的子應(yīng)用路由活動規(guī)則,同時 vue
路由也會監(jiān)聽路由變化翔悠。
因為主應(yīng)用有自己的業(yè)務(wù)模塊业崖,需要支持頁面刷新,所以采用 hash
路由模式蓄愁。qiankun
官方 demo
使用的是 history
路由模式双炕。
那么,采用 hash
路由模式的話撮抓,主應(yīng)用路由會有 /#/
的前綴妇斤,比如主應(yīng)用的 resource
組件路由:
http://localhost:8889/#/resource
假設(shè) history
路由模式下子應(yīng)用的注冊信息為:
{
name: 'live',
entry: '//localhost:7102',
container: '#subapp-viewport',
activeRule: '/live',
}
此時 qiankun
只有命中 url
為 http://localhost:8889/live
才會加載子應(yīng)用。
此處假設(shè)使用的路由切換代碼為:
this.$router.push({
path: '/live'
})
所以現(xiàn)在切換的 url
是 http://localhost:8889/#/live
胀滚,顯然不能匹配 /live
趟济,所以加載子應(yīng)用失敗。我們需要修改一下子應(yīng)用注冊的 activeRule
咽笼,使得匹配 hash
路由模式顷编。
為了區(qū)分開主應(yīng)用的自身模塊與子應(yīng)用的路由區(qū)別,子應(yīng)用的路由增加 /micro
前綴剑刑,比如 /micro/live
是子應(yīng)用的路由媳纬。
那么 hash
路由模式下子應(yīng)用的注冊信息變成:
{
name: 'live',
entry: '//localhost:7102',
container: '#subapp-viewport',
activeRule: '/#/micro/live',
}
路由切換代碼修改為:
this.$router.push({
path: '/micro/live'
})
這樣的話,主應(yīng)用路由切換后的 url
就能命中子應(yīng)用的 activeRule
了施掏。
同時钮惠,子應(yīng)用也需要將路由模式設(shè)置為 hash
模式,否則七芭,會出現(xiàn)在子應(yīng)用切換自身路由時素挽,改變主應(yīng)用 hash
路由的情況。比如子應(yīng)用切換自身路由 /about
狸驳,此時 url
會變成 http://localhost:8889/about/#/micro/live
预明,導(dǎo)致路由命中失敗。我們期望的 url
是 http://localhost:8889/#/micro/live/about
耙箍。
所以撰糠,為了兼容主應(yīng)用的 hash
模式路由,子應(yīng)用也需要設(shè)置為 hash
模式的路由辩昆,最終結(jié)果是實現(xiàn)子應(yīng)用路由與子應(yīng)用注冊在主應(yīng)用的 activeRule
的一致性阅酪。
下面會分別對主應(yīng)用與子應(yīng)用進行配置。
配置子應(yīng)用路由
子應(yīng)用是常規(guī) vue
項目,需要做調(diào)整的的是路由配置文件 /router.index.js
以及入口文件 main.js
术辐。
// router/index.js
let prefix = ''
// 判斷是 qiankun 環(huán)境則增加路由前綴
if(window.__POWERED_BY_QIANKUN__){
prefix = '/micro/live'
}
const routes = [
{
path: prefix + '/',
name: 'home',
component: Home,
},
{
path: prefix +'/about',
name: 'about',
component: About
},
]
// main.js
let router = null;
let instance = null;
function render(props = {}) {
const { container } = props;
router = new VueRouter({
// 默認(rèn)為 hash 路由模式
// base: window.__POWERED_BY_QIANKUN__ ? '/micro/live' : '/',
// mode: 'history',
routes,
})
// 判斷 qiankun 環(huán)境則進行路由攔截砚尽,判斷跳轉(zhuǎn)路由是否有 /micro 開頭前綴,沒有則加上
if(window.__POWERED_BY_QIANKUN__){
router.beforeEach((to, from, next) => {
if(!to.path.includes('/micro')){
next({
path: '/micro/live' + to.path
})
}else{
next()
}
})
}
instance = new Vue({
router,
store,
render: h => h(App),
}).$mount(container ? container.querySelector('#app') : '#app');
}
配置主應(yīng)用路由
主應(yīng)用需要修改的是子應(yīng)用注冊的路由匹配規(guī)則辉词,因為主應(yīng)用采用的是 hash
路由模式尉辑,qiankun
需要命中路由的話,activeRule
需要帶上 /#/
前綴较屿。
// App.vue
const apps = [
{
name: 'live',
entry: '//localhost:7101',
container: '#subapp-viewport',
activeRule: '/#/micro/live',
}
]
registerMicroApps(apps,
{
beforeLoad: [
app => {
console.log('[LifeCycle] before load %c%s', 'color: green;', app.name);
},
],
beforeMount: [
app => {
console.log('[LifeCycle] before mount %c%s', 'color: green;', app.name);
},
],
afterUnmount: [
app => {
console.log('[LifeCycle] after unmount %c%s', 'color: green;', app.name);
},
],
},
)
// router/index.js
// httpRoutes 非必要,主要用于匹配 vue 應(yīng)用路由卓练,與路由通配符 {path: '*'} 一起使用
// 因為如果 vue 路由沒有匹配隘蝎,默認(rèn)是加載 Home 組件的
// 這樣 vue 路由視圖會與子應(yīng)用共存,不符合業(yè)務(wù)需求
//
// 當(dāng)前 httpRoutes 的路由配置是沒有設(shè)置 path 對應(yīng)的組件襟企,所以匹配的路由視圖必為空
//
// 如果不設(shè)置路由通配符嘱么,則 httpRoutes 不需要配置
const httpRoutes = [
{
path: '/micro/live',
name: 'Live'
// 沒有配置 component,則 router-view 不會加載組件
},
{
path: '/micro/live/:microRoute',
name: 'Live*'
// 沒有配置 component顽悼,則 router-view 不會加載組件
}
]
const router = new VueRouter({
routes: [
{
path: '/',
name: 'Home',
component: Home,
},
...httpRoutes,
{
path: '*',
component: Home
}
]
})
當(dāng) url
變化時曼振,首先主應(yīng)用進入的是 qiankun
的路由匹配規(guī)則,匹配到 /#/micro/live
時蔚龙,會加載子應(yīng)用冰评,同時主應(yīng)用的 vue
路由匹配到路由后不會加載路由組件,這樣就達(dá)到只顯示子應(yīng)用而 vue
路由組件不顯示的目的木羹。
當(dāng)子應(yīng)用內(nèi)部的 <router-link to="/about">
被點擊時甲雅,首先子應(yīng)用跳轉(zhuǎn)路由前會加上 /micro/live
前綴,實際上是 /micro/live/about
坑填,匹配到 about
路由抛人,然后在主應(yīng)用的 vue
路由中匹配到 /micro/live:microRoute
,同樣不會加載組件脐瑰。