[寫(xiě)在前面]
...等等再寫(xiě)...
[需要什么]
主應(yīng)用:
- 加載子服務(wù)的容器(不一定在 public/index.html 文件中,可以是任意位置),給一個(gè)id
- 加載子服務(wù)的路由,配置router,準(zhǔn)備一個(gè)空頁(yè)面占位
- 在 src.main.js 中,注冊(cè)子路由,啟動(dòng)qiankun
- 本地啟動(dòng)的話,是否需要代理接口,proxy自己配一下
子應(yīng)用:
- 子服務(wù)的入口容器,id最好與主應(yīng)用的容器id 區(qū)分開(kāi),使用不同的命名
- 在 src.main.js 中,導(dǎo)出qiankun需要的生命周期
- 新增 src/public-path.js ,進(jìn)行配置
- 路由改造,使用與主應(yīng)用相同的路由路徑,防止無(wú)法找到頁(yè)面
- 在 vue.config.js 中,進(jìn)行改造
[開(kāi)始之前]
先使用vue3 + vue-cli 創(chuàng)建兩個(gè)項(xiàng)目
主應(yīng)用和子應(yīng)用 最好使用同一版本的組件庫(kù),不然可能報(bào)錯(cuò),或產(chǎn)生樣式問(wèn)題
[開(kāi)始啦]
安裝qiankun,我這里安裝的是qiankun@2.10.16
主應(yīng)用:
- 增加路由配置
import { RouteRecordRaw } from "vue-router"
export const route: RouteRecordRaw = {
path: "subView",
name: "子應(yīng)用",
meta: { title: "子應(yīng)用", icon: "mes-user" },
redirect: "/subView",
children: [
{
path: "subView1",
name: "子應(yīng)用菜單",
component: () => import("@/views/empty.vue"),
meta: { title: "子應(yīng)用"},
children: [
{
path: ":w",
component: () => import("@/views/empty.vue"),
},
],
},
],
}
export default route
// @/views/empty.vue 空白頁(yè)面
<template>
<div style="background: tansparent"></div>
</template>
<script setup lang="ts"></script>
<style lang="less" scoped></style>
- 子應(yīng)用容器
<div id="sub-container"></div>
- 注冊(cè)子應(yīng)用
// src/main.ts
import { registerMicroApps, start, prefetchApps } from "qiankun"
// 匹配路由路徑
const getActiveRule = (hash) => (location) => {
return location.hash.startsWith(hash)
}
// 注冊(cè)子應(yīng)用
registerMicroApps(
[
{
name: "subApp",
entry: "http://localhost:8081", // 發(fā)布上線后,換成該路徑地址
container: "#sub-container",
activeRule: getActiveRule("#/djTrans/projectCollection"), // "/#/djTrans/transTool",
props: {
msg: "我是來(lái)自主應(yīng)用的值-vue", // 主應(yīng)用向微應(yīng)用傳遞參數(shù)
},
},
]
)
// 啟動(dòng) qiankun
start({ sandbox: false }) // 沙箱,防止樣式影響
- 代理自己配一下
"/subView": {
target: proxy3,
changeOrigin: true,
onProxyReq(proxyReq, req, res) {
originHost = req.headers["x-forwarded-for"]
proxyReq.setHeader("Cookie", "token=" + process.env.VUE_SERVER_TOKEN)
},
},
子應(yīng)用:
- 導(dǎo)出qiankun需要的生命周期
// src/main.ts
import store from './store';
import antd from 'ant-design-vue';
import 'ant-design-vue/dist/reset.css';
import '@/assets/global.less';
import { createApp } from 'vue';
import 'qiankun';
import { createRouter, createWebHistory } from 'vue-router';
import App from './App.vue';
import routes from './router';
let app;
let router;
let history;
function render(props = { container: undefined }) {
history = createWebHistory(process.env.BASE_URL);
router = routes;
app = createApp(App);
app.use(antd);
app.use(store);
const { container } = props;
app.use(router).mount(container ? container.querySelector('#sub-app') : '#sub-app');
}
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
// 子組件暴露三個(gè)函數(shù)
export async function bootstrap(props) {
console.log('我是bootstrap項(xiàng)目函數(shù)', props);
}
export async function mount(props) {
console.log('我是mount項(xiàng)目函數(shù)', props);
render(props);
}
export async function unmount(props) {
console.log('我是vue項(xiàng)目unmount函數(shù)', props);
history = null;
app = null;
router = null;
}
- 新增 src/public-path.js ,進(jìn)行配置
if (window.__POWERED_BY_QIANKUN__) {
// __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
__webpack_require__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
__webpack_public_path__ = window.__POWERED_BY_QIANKUN__
? window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
: 'http://111.11.51.41:8081/'; // 填寫(xiě)你的實(shí)際部署地址
- 按照主應(yīng)用的路由,修改子應(yīng)用路由
const router = createRouter({
history: createWebHashHistory(process.env.BASE_URL),
routes
});
- 修改配置
// vue.config.js
const { name } = require('./package');
module.exports = defineConfig({
// 打開(kāi)文件訪問(wèn)的相對(duì)路徑 獨(dú)立項(xiàng)目 通過(guò)項(xiàng)目根目錄訪問(wèn)
publicPath: 'http://localhost:8081', // '/' // 部署上線后,換成子應(yīng)用打開(kāi)的路徑
// transpileDependencies: true, // 轉(zhuǎn)義依賴(lài)項(xiàng)
productionSourceMap: false,
configureWebpack: {
output: {
library: `${name}-[name]`,
// library: 'vueApp',
libraryTarget: 'umd',
chunkLoadingGlobal: `webpackJsonp_${name}` // jsonpFunction
}
},
devServer: {
open: false,
port: 8081,
host: 'localhost',
https: false,
proxy: {
'/': {
target: proxy3,
ws: false,
changeOrigin: true,
}
},
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': '*'
}
}
});
參考文檔
qiankun官網(wǎng):https://qiankun.umijs.org/zh/guide
webpack官網(wǎng):https://www.webpackjs.com/
qiankun引入vue3子項(xiàng)目實(shí)踐:https://zhuanlan.zhihu.com/p/618433202
簡(jiǎn)書(shū)例子:http://www.itdecent.cn/p/b8599fddc6bb
vue使用qiankun框架心得和踩坑記錄:https://blog.csdn.net/weixin_40883720/article/details/122358162
qiankun報(bào)錯(cuò):
https://blog.csdn.net/m0_67401382/article/details/123426513
https://blog.csdn.net/haoran87/article/details/136660839
遇到的問(wèn)題

[報(bào)錯(cuò)]qiankun報(bào)錯(cuò):Maximum call stack size exceeded
[我的解決] 主應(yīng)用啟動(dòng)乾坤時(shí),給參數(shù)start({ sandbox: false })

[報(bào)錯(cuò)]qiankun報(bào)錯(cuò):You need to export lifecycle functions in djTrans entry
[我的解決] 子應(yīng)用output配置有問(wèn)題,主應(yīng)用沒(méi)有找到子應(yīng)用
[報(bào)錯(cuò)]qiankun報(bào)錯(cuò):[qiankun] prefetch starting after vueApp mounted...
[報(bào)錯(cuò)]qiankun報(bào)錯(cuò):[qiankun:sandbox] vueApp modified global properties
[報(bào)錯(cuò)]qiankun報(bào)錯(cuò):[qiankun]: Wrapper element for djtranstool is not existed!restore...
[我的解決] 這報(bào)錯(cuò),我忘了怎么解決的了,先記上,證明我遇見(jiàn)過(guò),并解決了