微前端是一種多個團隊通過獨立發佈功能的方式來共同構建現代化 web 應用的技術手段及方法策略。
微前端借鑑了微服務的架構理念,將一個龐大的前端應用拆分爲多個獨立靈活的小型應用,每個應用都可以獨立開發、獨立運行、獨立部署,再將這些小型應用聯合爲一個完整的應用。微前端既可以將多個項目融合爲一,又可以減少項目之間的耦合,提升項目擴展性,相比一整塊的前端倉庫,微前端架構下的前端倉庫傾向於更小更靈活。
主應用
安裝
npm i qiankun -S
registerMicroApps方法,新建一個hooks文件,生成一個usehooks供全局使用,然後在需要微前端的地方調用即可
- 當路由跳轉匹配上qiankun配置的規則時,則會跳轉到子應用的路由如(/one/pagesone)則匹配子應用的pagesone的路由
import { registerMicroApps, runAfterFirstMounted, start } from "qiankun/es"
import { RegistrableApp } from "qiankun"
export const useQiankun = () => {
// const app = [
// {
// name: 'ms-one', // 微應用的名稱
// entry: 'http://localhost:3001/', // 微應用的入口
// container: '#one-container', // 微應用的容器節點的選擇器
// activeRule: '/one' // 微應用的激活規則匹配路由規則
// }]
const initQiankun = (app: Array<RegistrableApp<Record<string, unknown>>>, mounted = () => {}) => {
registerMicroApps(app, {})
// 第一個微應用 mount 後需要調用的方法,比如開啓一些監控或者埋點腳本
runAfterFirstMounted(() => {
mounted()
})
start({ prefetch: true }) // 啓動
}
return { initQiankun }
}
使用
對應的頁面創建dom、生成對應的app
<script lang="ts" setup>
import { onMounted } from 'vue'
import { useQiankun } from './hooks/useQiankun'
const app = [
{
name: 'ms-one',
entry: 'http://localhost:3001/',
container: '#one-container',
activeRule: '/one'
}]
const { initQiankun } = useQiankun()
onMounted(() => {
initQiankun(app)
})
</script>
<template>
<div class="app-one-container">
<div id="one-container"></div>
</div>
</template>
子應用
安裝vite的插件 vite-plugin-qiankun
npm i vite-plugin-qiankun -D
vite.config.ts中配置
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import Pages from 'vite-plugin-pages'
import qiankun from "vite-plugin-qiankun"
export default defineConfig({
plugins: [
vue(),
Pages({
dirs: 'src/views'
}),
qiankun("ms-one", {
useDevMode: true
})
],
base: "/ms-one/",
server: {
port: 3001
},
resolve: {
alias: {
"@": path.resolve(__dirname, "src")
}
}
})
mian.js 中監聽是子應用使用還是主應用過來
import { createApp } from 'vue'
import '@/assets/style.css'
import App from './App.vue'
import { createWebHistory } from 'vue-router'
import createRouter from "./router"
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
let router: any = null
let instance: any = null
let history: any = null
function render(props: any | undefined) {
console.log("__POWERED_BY_QIANKUN__", qiankunWindow.__POWERED_BY_QIANKUN__)
const container = props ? props.container : undefined
history = createWebHistory(qiankunWindow.__POWERED_BY_QIANKUN__ ? '/one' : '/ms-one')
router = createRouter(history)
instance = createApp(App)
instance.use(router)
instance.mount(container ? container.querySelector('#app') : '#app')
}
renderWithQiankun({
mount(props: any) {
render(props)
instance.config.globalProperties.$onGlobalStateChange = props.onGlobalStateChange
instance.config.globalProperties.$setGlobalState = props.setGlobalState
},
bootstrap() {
console.log('%c%s', 'color: green;', 'vue3.0 app bootstraped')
},
unmount() {
instance.unmount()
instance._container.innerHTML = ''
instance = null
router = null
history.destroy()
},
update() {
console.log('update')
}
})
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
render(undefined)
}
最後在建立對應的路由即可完成主應用對子應用的跳轉