1 前言
前言摘抄自 qiankun 官网微前端介绍
1.1 微前端定义
微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略。微前端架构旨在解决单体应用在一个相对长的时间跨度下,由于参与的人员、团队的增多、变迁,从一个普通应用演变成一个巨石应用(Frontend Monolith)后,随之而来的应用不可维护的问题。这类问题在企业级 Web 应用中尤其常见。
1.2 微前端架构核心价值
- 技术栈无关
主框架不限制接入应用的技术栈,微应用具备完全自主权 - 独立开发、独立部署
微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新 - 增量升级
在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略 - 独立运行时
每个微应用之间状态隔离,运行时状态不共享
2 主应用接入 qiankun
2.1 安装 qiankun
npm i qiankun
2.2 基于路由配置方式接入
import { registerMicroApps, start } from 'qiankun'
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.mount('#app')
registerMicroApps(
[
{
name: 'subApp',
entry: 'http://localhost:8000',
container: '#sub-app-container',
activeRule: '/home',
props: {
}
}
],
{
}
)
start()
<template>
<!-- 提供挂载容器 -->
<div id="sub-app-container"></div>
</template>
2.3 手动加载微应用方式接入
<template>
<button @click="loadApp">挂载微应用</button>
<button @click="unloadApp">卸载微应用</button>
<!-- 提供挂载容器 -->
<div id="sub-app-container"></div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { loadMicroApp } from 'qiankun'
let microApp: any = null // 微应用实例
const loadApp = () => {
if (microApp) return
microApp = loadMicroApp({
name: 'subApp', // 必须与微应用注册名字相同
entry: 'http://localhost:8000', // 入口路径,开发时为微应用所启本地服务,上线时为微应用线上路径
container: '#sub-app-container',
props: {
// 主应用向微应用传递参数
}
})
microApp.mountPromise.then(() => {
// 微应用加载完成后回调
})
}
const unloadApp = () => {
if (!microApp) return
microApp.unmount() // 卸载微应用
}
</script>
3 微应用接入 qiankun
3.1 安装 vite-plugin-qiankun
qiankun 暂不支持 Vite 方式接入,需安装 vite-plugin-qiankun
npm i vite-plugin-qiankun
3.2 接入 qiankun
import { defineConfig } from 'vite'
import qiankun from 'vite-plugin-qiankun'
export default defineConfig((mode) => {
return {
plugins: [
qiankun('subApp', {
useDevMode: true,
}),
],
}
})
import { createApp } from 'vue'
import App from './App.vue'
import {
renderWithQiankun,
qiankunWindow,
QiankunProps,
} from 'vite-plugin-qiankun/dist/helper'
const render = (props: QiankunProps = {}) => {
const { container } = props
const app: string | Element = container?.querySelector('#subApp') || '#subApp'
createApp(App).mount(app)
}
const initQianKun = () => {
renderWithQiankun({
bootstrap() {
console.log('微应用:bootstrap')
},
mount(props) {
console.log('微应用:mount', props)
render(props)
},
unmount(props) {
console.log('微应用:unmount', props)
},
update(props) {
console.log('微应用:update', props)
},
})
}
qiankunWindow.__POWERED_BY_QIANKUN__ ? initQianKun() : render()
4 应用间通信
4.1 全局挂载
{
name: 'subApp',
entry: 'http://localhost:8000',
container: '#sub-app-container',
props: {
msg: '主应用参数'
}
}
const testFun = () => {}
window[subApp] = { testFun }
4.2 initGlobalState
该 API 虽然还在官方文档中展示,但 qiankun 源代码中已不推荐使用,但未提供新的通信方案
import { initGlobalState, MicroAppStateActions } from 'qiankun'
const state = {
msg: '主应用消息'
}
const actions: MicroAppStateActions = initGlobalState(state)
export default actions
<template>
<button @click="clickButton">主应用按钮</button>
</template>
<script setup lang="ts">
import actions from '@/actions'
actions.onGlobalStateChange((state, prevState) => {
console.log(state, prevState)
})
const clickButton = () => {
actions.setGlobalState({
msg: '主应用修改主应用消息'
})
}
</script>
const initQianKun = () => {
renderWithQiankun({
bootstrap() {
console.log('微应用:bootstrap')
},
mount(props) {
console.log('微应用:mount', props)
props.actions.setGlobalState({ msg: '微应用修改主应用消息' })
render(props)
},
unmount(props) {
console.log('微应用:unmount', props)
},
update(props) {
console.log('微应用:update', props)
},
})
}
|