Vue3子应用在umi中qiankun接入
当项目比较庞大,集成平台之类的,需要耦合多种业务,那么采用微前端维护是比较合理的,这里介绍如何将vue子应用接入umi主应用,并实现子应用与主应用之间的通信。
一、子应用 Vite + vue3
安装vite插件
npm i -D vite-plugin-qiankun
配置 vite.config
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import qiankun from 'vite-plugin-qiankun'; // 引入适配器
export default defineConfig({
plugins: [
vue(),
qiankun('subApp', { // 主应用登记的一模一样!
useDevMode: process.env.NODE_ENV === "development" // 开发模式也要能上台排练
})
],
server: {
port: 6104, // 端口,必须和主应用 `entry` 一致
origin: 'http://localhost:6104' // 确保资源能找到回家的路
},
base: process.env.NODE_ENV === 'production'
? 'http://dx.test.vip/' // 完整的部署地址
: '/', // 本地运行
});
改造main.ts
import { createApp } from "vue"
import App from "./App.vue"
import { setupRouter } from "./router/index"
import { setupStore } from "./store/index"
import { loadScopedIconfont } from "@/utils/iconfont"
import { renderWithQiankun, qiankunWindow } from "vite-plugin-qiankun/dist/helper"
import "@/styles/index.less"
import "@/components/MixTable/styles/table.less"
loadScopedIconfont({
iconfontUrl: "//at.alicdn.com/t/c/font_2885052_dsy4qqlpgxs.css",
subAppName: "test-web"
})
let app: any = null // 保存 Vue 应用实例
// 渲染逻辑
function renderStandaloneApp(container: any = null) {
app = createApp(App)
setupRouter(app, container ? "/subApp" : "/")
setupStore(app)
const rootContainer = container ? container.querySelector("#app") : "#app"
app.mount(rootContainer)
}
// 判断独立渲染模式
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
renderStandaloneApp()
}
// Qiankun 生命周期钩子
renderWithQiankun({
bootstrap() {
console.log("subApp bootstrap")
},
mount(props) {
console.log("subApp mount", props)
renderStandaloneApp(props.container)
},
update(props) {
console.log("subApp update", props)
},
unmount() {
console.log("subApp unmount")
app?.unmount()
app = null
}
})
路由注册根据子应用带上base
export const setupRouter = (app: App<Element>, base = "/") => {
const router = createRouter({
history: createWebHistory(base),
routes
})
app.use(router)
router.beforeEach(beforeRouter)
}
iconfont与主应用隔离
动态加载iconfont资源,重写iconfont的font-family,为每个icon添加子应用的class父级类包裹
export const loadScopedIconfont = async ({ iconfontUrl = "", subAppName = "" }) => {
if (!iconfontUrl) return
const response = await fetch(iconfontUrl)
let cssText = await response.text()
// 为所有 iconfont 相关的选择器添加命名空间
cssText = cssText
.replace(/(\.icon[^,{};]*)/g, `.${subAppName} $1`)
.replace(/font-family: "iconfont"/g, `font-family: "${subAppName}-iconfont"`)
const style = document.createElement("style")
style.textContent = cssText
document.head.appendChild(style)
}
在App.vue中用子应用确定的隔离class包裹路由
<div class="test-web">
<router-view />
</div>
二、主应用 umijs
qiankun注册子应用
export default {
qiankun: {
master: {
apps: [
{
name: 'subApp',
entry: 'http://subApp.molsci.vip',
},
],
},
}
};
路由注册子应用路由
export default [
{
path: '/',
component: '@/components/Layout',
routes: [
{
path: '/subApp/*',
microApp: 'subApp',
},
]
}
]
向子应用传值
在app.tsx中导出useQiankunStateForSlave
export function useQiankunStateForSlave() {
const [initAppState, setInitAppState] = React.useState<any>({
_appName: 'Molsci',
});
return {
initAppState,
setInitAppState,
};
}
三、主应用和子应用通信
Qiankun 提供了 <font style="color:rgb(77, 77, 77);">initGlobalState</font>传递初始参数
主应用传递
export function useQiankunStateForSlave() {
const [initAppState, setInitAppState] = React.useState<any>({
_appName: 'myApp',
});
return {
initAppState,
setInitAppState,
};
}
子应用回传
renderWithQiankun({
mount(props) {
/** 监听主应用透传的state变化 */
props.onGlobalStateChange(
(newState, oldState) => {
console.log(' Vue子应用监听到:', newState);
},
true // true 表示立刻用当前状态触发一次上面的回调
);
// 子应用更新主应用中的state
function updateProjectLoading() {
props.setGlobalState({
loading: false // 只能更新 initialState 里已有的一级属性!
});
}
},
});
四、子应用部署
1.Nginx配置
需要配置能跨域访问,才能保证主应用在不同域能拉取到子应用
server {
listen 80;
server_name dx.test.vip;
location / {
root E:/deng/mssk-web/test-web/dist;
index index.html index.htm;
try_files $uri $uri/ /index.html;
# 添加CORS头
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization";
}
}
802

被折叠的 条评论
为什么被折叠?



