微前端qiankun改造日漸龐大的項目教程
項目背景
很多小伙伴在工作中都碰到過和我一樣的場景,手上的某個項目越來越大,眼看著每次build時間越來越長,吐了??。在杭州某獨角獸我碰到了這樣的一個項目,他叫運營后臺,聽名字就知道,他的主要用戶是運營人員。問題就是隨著公司業(yè)務的越來越多,這個運營后臺承擔的已經(jīng)不是某一塊業(yè)務了,而是所有業(yè)務的運營操作的中后臺都在這上面。你可以這樣理解,這個系統(tǒng)的每個一級菜單都是一塊獨立的業(yè)務,相互之間沒有任何瓜葛;按常規(guī)的理解,這應該是單獨的每一個project比較合理,但是正因為他的用戶又都是公司的同一群人,他們早已經(jīng)習慣就在運營后臺上去找自己的菜單進行業(yè)務操作,拒不接受在他的收藏夾里多出來好幾個項目地址。那我們有沒有一個辦法讓我們的項目更好維護,又能讓用戶不改變他們使用同一個項目的期望呢。這就是寫這篇文章的初衷,就是微前端??!????
微前端的好處
除了可以解決上面的問題以外,你想想,只要我們把項目改造成了微前端,那每個業(yè)務都是獨立的project,只不過最終用戶都是在一個主項目里去使用,那我們每個project的技術棧也不用定死了,就不存在老項目的技術棧是vue,以至于后面的項目都必須要用vue了,你也可以用react,這就很香不是嗎。微前端的原理就是項目被拆成了父子關系,通過基座去引用了子應用,子應用之間是互相隔離的????
qiankun
可能是你見過最完善的微前端解決方案??——官方是這么介紹的,基于single-spa,這里我就不詳細介紹了,感興趣的去看看文檔,地址丟給你
改造過程
首先我先用vue2-admin-cli——我自己做的腳手架工具,創(chuàng)建兩個vue-admin項目來演示,一個作為qiankun基座,另外一個就是我要引用的子應用。
全局安裝腳手架 npm install -g vue2-admin-cli or yarn global add vue2-admin-cli 創(chuàng)建項目 vue2-admin-cli init <project_name> 安裝依賴 yarn 啟動項目 yarn serve
運行起來就是這樣的

現(xiàn)在我們開始分別改造基座qiankun-base和子應用qiankun-vue,我想達到的效果是主應用qiankun-base只保留header sider footer的一個基本layout的布局,content部分全部加載子應用
qiankun-base
yarn add qiankun # 或者 npm i qiankun -S
修改package.json啟動命令修改啟動端口
"serve": "vue-cli-service serve --port 80 --open"
src/router/index.ts修改路由模式為history
const createRouter = () =>
new VueRouter({
mode: "history",
routes: routes as any,
});
修改vue.config.js 我這里之前用的路由模式是hash 上線配置了publicPath 導致改為history以后靜態(tài)資源加載路徑有問題所以修改
module.exports = {
// publicPath: "./",
devServer: {
disableHostCheck: true, // 關閉host檢查
},
};
在入口文件src/main.ts下注冊微應用并啟動:
import { registerMicroApps, start } from "qiankun";
registerMicroApps([
{
name: "qiankunVue",
entry: "http://localhost:8080", //子應用的啟動端口修改為8080,基座使用80,不要相同
container: "#qiankunVue", //加載子應用的容器
activeRule: "/qiankunVue", //路由匹配規(guī)則
},
]);
// 啟動 qiankun
start();
在你要放置子應用的位置增加一個容器用于加載子應用
src/components/layout/index.vue
<template>
<el-container direction="vertical" style="height: 100%">
<Header />
<el-container style="overflow: auto">
<el-aside width="250px">
<Menu />
</el-aside>
<el-main>
<el-breadcrumb
separator-class="el-icon-arrow-right"
v-if="showBreadcrumb"
>
<template v-for="(route, index) in matchedRoutes">
<el-breadcrumb-item
v-if="
(route.meta && route.meta.breadcrumbTo === false) ||
index === matchedRoutes.length - 1
"
:key="route.path"
>
{{ route.meta.title }}
</el-breadcrumb-item>
<el-breadcrumb-item
v-else
:key="route.path"
:to="{ path: route.path }"
>
{{ route.meta.title }}
</el-breadcrumb-item>
</template>
</el-breadcrumb>
<!-- 本身的路由加載 -->
<router-view style="margin-top: 20px" />
<!-- 子應用加載容器 -->
<div id="qiankunVue" style="width: 100%; height: 100%" />
</el-main>
</el-container>
</el-container>
</template>
將主應用之前的路由配置進行修改,不渲染自己的內(nèi)容了,因為要改成去加載子應用的內(nèi)容才是我們想要的,我的左側(cè)菜單欄sider也是用路由配置這份文件生成的,所以我只需要注釋這些路由要渲染的components就行,讓他只充當一個生成sider菜單欄的作用,但是注意要保留容器所在的layout,因為我的子應用加載容器在這里面,加載子應用之前你必須保證容器被加載了
src/router/config.ts
const routes: Array<IBaseRouter> = [
{
path: "/",
redirect: "/home",
hidden: true,
},
{
path: "/login",
name: "login",
hidden: true,
component: () => import("../views/Login.vue"),
},
//保證子應用加載時容器頁面必須加載
{
path: "/qiankunVue/*",
name: "qiankunVue",
hidden: true,
component: Layout,
},
{
path: "/qiankunVue/home",
name: "home",
component: Layout,
redirect: "/qiankunVue/home/index",
meta: {
title: "首頁",
icon: "el-icon-s-home",
},
children: [
{
path: "index",
name: "index",
hidden: true,
// component: () => import("../views/Home.vue"),
meta: {
title: "首頁",
breadcrumb: false,
},
},
{
path: "bar/:width/:height",
name: "bar",
props: true,
hidden: true,
// component: () => import("@/components/echarts/Bar.vue"),
meta: {
title: "柱狀圖",
activeMenu: "/home/index",
},
},
{
path: "pie/:width/:height",
name: "pie",
props: true,
hidden: true,
// component: () => import("@/components/echarts/Pie.vue"),
meta: {
title: "餅圖",
activeMenu: "/home/index",
},
},
{
path: "line/:width/:height",
name: "line",
props: true,
hidden: true,
// component: () => import("@/components/echarts/Line.vue"),
meta: {
title: "折線圖",
activeMenu: "/home/index",
},
},
],
},
.....
{
path: "*",
redirect: "/error/404",
hidden: true,
},
];
export default routes;
改完之后刷新看一看,這樣基座項目就改造好了,保留了基本頁面的框架,中間的內(nèi)容到時候都由子應用來填充就行了

qiankun-vue
修改package.json啟動命令修改啟動端口
"serve": "vue-cli-service serve --port 8080 --open"
入口文件 src/main.ts 修改
let vm: any = null;
function render(props: any = {}) {
const { container } = props;
vm = new Vue({
router,
store,
render: (h) => h(App),
}).$mount(container ? container.querySelector("#app") : "#app");
}
// 在被qiankun引用時 修改運行時的 `publicPath`
if ((window as any).__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = (window as any).__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
// 獨立運行時
if (!(window as any).__POWERED_BY_QIANKUN__) {
render();
}
導出三個生命周期函數(shù)
export async function bootstrap() {
console.log("[vue] vue app bootstraped");
}
export async function mount(props: any) {
console.log("[vue] props from main framework", props);
render(props);
}
export async function unmount() {
vm.$destroy();
vm.$el.innerHTML = "";
vm = null;
}
export default vm;
src/router/index.ts修改路由模式并增加base(和主應用設置的activeRule一致)
const createRouter = () =>
new VueRouter({
mode: "history",
base: "/qiankunVue",
routes: routes as any
});
打包配置修改(`vue.config.js`)
module.exports = {
devServer: {
disableHostCheck: true, // 關閉host檢查
headers: {
"Access-Control-Allow-Origin": "*", // 防止加載時跨域
},
},
configureWebpack: {
output: {
library: "qiankunVue",
libraryTarget: "umd", // 把微應用打包成 umd 庫格式
},
},
};
基座和子應用都修改完以后刷新看看,控制臺報錯了

立馬查看官方文檔,發(fā)現(xiàn)是因為我的子應用加載容器在基座的某個路由頁面即我的layout里面,文檔里指出必須保證微應用加載時主應用這個路由頁面也加載了,就很喜歡這種文檔????,于是立馬改一改
注釋之前qiankun-base注冊子應用時的啟動qiankun命令,改到路由頁面layout里面啟動
src/main.ts
// 啟動 qiankun
//start();
src/components/layout/index.vue
import { start } from "qiankun";
mounted() {
if (!(window as any).qiankunStarted) {
(window as any).qiankunStarted = true;
start();
}
}
重新刷新看看,成功了????,多少有點舒服了

接下來要做的就是把子應用再改造一下,在qiankun中就只需要展示子應用content的內(nèi)容,單獨運行的時候為了方便調(diào)試我們就保留layout布局??戳诉@么久的官方文檔,我當然知道用它就可以做出判斷__POWERED_BY_QIANKUN__,思路很清晰,沖他????
qiankun-vue
src/components/layout/index.vue
<template>
<el-container direction="vertical" v-if="isQiankun">
<el-main>
<el-breadcrumb
separator-class="el-icon-arrow-right"
v-if="showBreadcrumb"
>
<template v-for="(route, index) in matchedRoutes">
<el-breadcrumb-item
v-if="
(route.meta && route.meta.breadcrumbTo === false) ||
index === matchedRoutes.length - 1
"
:key="route.path"
>
{{ route.meta.title }}
<!-- {{ route.path }} -->
</el-breadcrumb-item>
<el-breadcrumb-item
v-else
:key="route.path"
:to="{ path: route.path }"
>
{{ route.meta.title }}
<!-- {{ route.path }} -->
</el-breadcrumb-item>
</template>
</el-breadcrumb>
<router-view style="margin-top: 20px" />
</el-main>
</el-container>
<el-container direction="vertical" style="height: 100%" v-else>
<Header />
<el-container style="overflow: auto">
<el-aside width="250px">
<Menu />
</el-aside>
<el-main>
<el-breadcrumb
separator-class="el-icon-arrow-right"
v-if="showBreadcrumb"
>
<template v-for="(route, index) in matchedRoutes">
<el-breadcrumb-item
v-if="
(route.meta && route.meta.breadcrumbTo === false) ||
index === matchedRoutes.length - 1
"
:key="route.path"
>
{{ route.meta.title }}
<!-- {{ route.path }} -->
</el-breadcrumb-item>
<el-breadcrumb-item
v-else
:key="route.path"
:to="{ path: route.path }"
>
{{ route.meta.title }}
<!-- {{ route.path }} -->
</el-breadcrumb-item>
</template>
</el-breadcrumb>
<router-view style="margin-top: 20px" />
</el-main>
</el-container>
</el-container>
</template>
<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
import Header from "./Header.vue";
import Menu from "./Menu.vue";
// import { IBaseRouter } from "@/router/config";
@Component({
name: "Layout",
components: { Header, Menu },
})
export default class Layout extends Vue {
private get showBreadcrumb() {
return this.$route?.meta?.breadcrumbAll !== false;
}
private get matchedRoutes() {
return this.$route.matched?.filter(
(v) => v.meta?.title && v?.meta?.breadcrumb !== false
);
}
private get isQiankun() {
return (window as any).__POWERED_BY_QIANKUN__;
}
}
</script>
<style lang="less" scoped></style>
至此完結撒花,改造結束????,看看效果 基座正常展示子應用

子應用單獨運行也正常展示,并且絲毫不影響開發(fā)體驗

項目地址
qiankun-base qiankun基座
qiankun-vue qiankun子應用
vue-admin ## vue 中后臺系統(tǒng)解決方案
vue2-admin-cli vue2-admin-cli是vue-admin的cli腳手架工具,支持快速搭建企業(yè)級中后臺項目模板
結尾
關于父子通信這個示例就不做概述,有興趣的可以自己看看文檔
以上就是微前端qiankun改造日漸龐大的項目教程的詳細內(nèi)容,更多關于微前端qiankun改造龐大項目的資料請關注腳本之家其它相關文章!
相關文章
微信小程序request出現(xiàn)400的問題解決辦法
這篇文章主要介紹了微信小程序request出現(xiàn)400的問題解決辦法的相關資料,需要的朋友可以參考下2017-05-05

