Appearance
一、配置主应用
1. 创建一个vue3项目,在项目中安装qiankun:
npm i qiankun -S2. 注册微应用并启动,在main.ts中:
js
import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import App from './App.vue'
import router from './router'
import { registerMicroApps, start } from 'qiankun';
import type { ObjectType, RegistrableApp } from "qiankun";
const app = createApp(App)
// 注册所有图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
const appConfig: RegistrableApp<ObjectType>[] = [{
name: 'vue-first-app', // 微应用的名称,需要唯一
entry: '/app-vue-history/', // 微应用的入口,部署配置
// entry: '//localhost:3001', // 微应用的入口,本地开发
container: '#vue-first-app', // 主应用中用于渲染微应用的容器, 微应用渲染的节点容器
activeRule: '/app-vue-history', // 微应用的激活规则,匹配路由,跟子应用路由要相同
},]
registerMicroApps(appConfig)
// 启动 qiankun
start({
prefetch: 'all',
sandbox: {
experimentalStyleIsolation: true,
}
});
app.use(createPinia())
app.use(router)
app.use(ElementPlus)
app.mount('#app')3. 注册子应用路由
ts
import { createRouter, createWebHistory } from 'vue-router'
import AppView from '../views/AppView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: AppView,
},
// 微应用1相关路由 - 这些路由将会被qiankun接管,但需要在主应用中保留占位
{
path: '/app-vue-history/:pathMatch(.*)*',// app-vue-history要跟activeRule的值一样,用于匹配路由,代表当前所有app-vue-history的路由,都访问子应用页面
name: 'vue-history',
component: AppView,
},
],
})
export default router4. 增加子应用路由页面
在路由的component页面(AppView)增加配置
vue
<script setup lang="ts">
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import TheWelcome from '../components/TheWelcome.vue'
const route = useRoute()
// 计算当前是否显示微应用
const isMicroApp = computed(() => {
return route.path.startsWith('/app-vue-history')
})
// 计算当前微应用的ID
const microAppId = computed(() => {
if (route.path.startsWith('/app-vue-history')) {
return 'vue-first-app' // 对应注册子应用时的container
}
return ''
})
</script>
<template>
<div class="app-view-container">
<!-- 主应用内容 -->
<main v-if="!isMicroApp" class="main-app-content">
<TheWelcome />
</main>
<!-- 微应用容器 -->
<div v-else class="micro-app-container">
<!-- 微应用加载指示器 -->
<div class="loading-indicator">
<p>正在加载微应用...</p>
</div>
<!-- 微应用挂载点 -->
<div :id="microAppId" class="micro-app-mount"></div>
</div>
</div>
</template>5. 增加路由跳转
vue
<!-- 统一根据规则activeRule:app-vue-history,进行子应用路由匹配, home和about是子应用内部的路由 -->
<el-menu-item index="/app-vue-history/home">首页</el-menu-item>
<el-menu-item index="/app-vue-history/about">关于</el-menu-item>二、配置子应用
1. qiankun目前不支持vite,安装插件vite-plugin-qiankun
npm install vite-plugin-qiankun2. 修改vite.config.ts文件
ts
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
import qiankun from "vite-plugin-qiankun"; // 配置乾坤插件
let path = process.env.NODE_ENV == "development" ? "/app-vue-history/" : "/app-vue-history/";
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
qiankun("vue-first-app", { //和注册子应用时的name一致
useDevMode: true,
})
],
// 因为主应用activeRule:app-vue-history,开发模式下统一在次配置app-vue-history,就不用在路由中多次填写app-vue-history。
// 部署情况,需要和entry一样。
base: path,
server: {
port: 3001, // 本地开发端口需要对应主应用注册的端口号
cors: true, // 启用 CORS
headers: {
'Access-Control-Allow-Origin': '*', // 开发环境下允许所有来源
}
},
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
},
},
})3. 路由配置
ts
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
name: "app1Home",
path: "/home", // 因为base填写了:app-vue-history,这就不用写了。
component: HomeView,
},
{
path: '/about',
name: 'app1About',
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import('../views/AboutView.vue'),
},
],
})
export default router4. 修改main.ts
ts
import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import {
renderWithQiankun,
qiankunWindow,
type QiankunProps,
} from "vite-plugin-qiankun/dist/helper";
function render(props: QiankunProps = {}) {
const { container } = props;
const app = createApp(App);
app.use(createPinia());
app.use(router);
container
// app1要对应html文件中的id
? app.mount(container.querySelector("#app1") as HTMLElement)
: app.mount("#app");
}
function initApp() {
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
console.log("%c 独立渲染", "color: red; font-size: 20px;");
render();
return;
}
renderWithQiankun({
mount(props) {
console.log("%c qiankun 渲染", "color: red; font-size: 20px;");
console.log(props);
render(props);
},
bootstrap() {
console.log("bootstrap");
},
unmount(props) {
console.log("unmount", props);
},
update(props) {
console.log("update", props);
},
});
}
initApp() 三、部署到Nginx
Nginx配置:
conf
server {
listen 80;
server_name app1.myapp.local; # 域名
# 主应用
location / {
root html;
index index.html index.htm;
try_files $uri $uri/ /index.html; # 支持Vue路由的history模式
}
#子应用
location /app-vue-history {
alias html/child/vue-history/; #通过alias替换 子应用构建后的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 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
add_header Cache-Control no-cache; # 强制刷新,要不子应用更新后,访问不刷新
if ($request_method = 'OPTIONS') {
return 204;
}
}
}Nginx目录
└── html/ # 根文件夹
|
├── child/ # 存放所有微应用的文件夹
| ├── vue-history/ # 存放微应用 vue-history 的文件夹
├── index.html # 主应用的index.html
├── css/ # 主应用的css文件夹
├── js/ # 主应用的js文件夹