前言
公司想要进行项目升级,把之前老套的淘汰的项目框架使用Vue3重写,并且后端也由.net5.0升级为8.0,还想把全部项目整合到一起,变成一个BS的大平台项目,由此引用微前端框架,我选择了qiankun,原因无他,看起来相比于其他框架简单。由于在使用qiankun过程中出现了不少问题,在此做下笔记。
项目环境选择
电脑运行环境:nodeJS ,下载地址:Node.js 。下载和安装环境略过。
项目环境我使用的是 Vite+Js+pinia。原因如下:
- Vite :Vue3支持的编译速度最快的构建器;
- JavaScript : 其实Js和Ts无所谓,如果习惯Ts写法推荐Ts,据说编译速度会更快;
- Pinia :Pinia有着更好的性能表现,并且管理状态的方式相对Vuex来说更加简单,就是插件没有Vuex丰富。
创建主应用
控制台输入命令:
npm create vite@latest
输入项目名称以及选择好相关的配置比如Vue和Js:
项目创建完成后将该应用作为主应用运行,当然你可以选择主应用为框架,其他子应用作为内容兼容进来。
安装相关插件(qiankun、pinia、路由等):
npm:
npm install qiankun -s
npm install pinia -s
npm install pinia-plugin-persistedstate -s
npm install vue-route -s
npm install element-plus --save
npm install -D unplugin-vue-components unplugin-auto-import //按需导入ElementPlus
修改一下Vite.config.js的项目运行配置,完整代码如下,其中引用了ElementPlus优化页面:
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import vue from '@vitejs/plugin-vue'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
server: {
port: 5111,
headers: {
// 重点1: 允许跨域访问子应用页面
'Access-Control-Allow-Origin': '*',
},
},
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
})
主应用的main.js中添加代码,完整main.js如下,自行对比修改了哪些内容:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
// 主应用入口文件 main.js 或者 app.js
import { registerMicroApps, start } from 'qiankun'
const app = createApp(App)
app.use(router)
app.mount('#mainApp') //修改挂载容器(包括index.html),建议主子应用都别用app,定义好不重复的名称,不然容易出现挂载异常
registerMicroApps(
[
{
name: 'qiankun-subApp', // 子应用的名称
entry: '//localhost:5555', // 子应用的入口地址
container: '#qiankun-subApp', // 挂载的DOM元素
activeRule: '/subHomePage', // 激活子应用的路由规则(子应用首次访问的路由地址)
},
],
{
//还有一些生命周期 如果需要可以根据官网文档按需加入
beforeMount(app) {
console.log('挂载前', app)
},
afterMount(app) {
console.log('卸载后', app)
},
}
)
start({
prefetch: false, //取消预加载
sandbox: { experimentalStyleIsolation: true }, //沙盒模式
})
页面的话,主应用只添加了两个路由作为参考页,home和about,然后主应用配置就完成了:
const routes = [
{
path: '/',
name: 'home',
component: () => import('@/views/home.vue'),
},
{
path: '/about',
name: 'about',
component: () => import('@/views/about.vue'),
}
]
现在主应用配置基本完成,美化一下样式,代码:
<template>
<div class="MainAppVue">
<el-menu
:default-active="activeIndex"
class="el-menu-demo"
mode="horizontal"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b"
@select="handleSelect"
>
<el-menu-item index="/">主应用Home</el-menu-item>
<el-menu-item index="/about">主应用About</el-menu-item>
<el-menu-item index="/subHomePage">子应用</el-menu-item>
</el-menu>
<router-view></router-view>
</div>
<!-- 子应用绑定容器 -->
<div id="qiankun-subAppContainer"></div>
</template>
<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const activeIndex = ref('/')
const handleSelect = (key, keyPath) => {
router.push({ path: key })
}
</script>
<style>
body {
margin: 0px;
}
</style>
效果如下:
创建子应用
和创建主应用的步骤一致,但是因为我们使用的是Vite构建,需要引用Vite插件来兼容qiankun环境:
npm install vite-plugin-qiankun -S
路由配置文件需要增加默认路由前缀,以下router.js完整代码:
import { createWebHistory, createRouter } from 'vue-router'
import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
const routes = [
{
path: '/',
name: 'home',
component: () => import('@/views/home.vue'),
},
{
path: '/about',
name: 'about',
component: () => import('@/views/about.vue'),
},
]
const router = createRouter({
history: createWebHistory(qiankunWindow.__POWERED_BY_QIANKUN__ ? `/subHomePage` : '/'), //这里需要配置/subHomePage,不然会点击跳转home到主应用的home
routes,
})
export default router
子应用main.js需要兼容子应用单独运行,所以要增加是不是qiankun环境的判断,vite引入的插件就很好解决了这个问题,完整代码如下:
import { createApp, ref } from 'vue'
import App from './App.vue'
import router from './router'
import {
renderWithQiankun,
qiankunWindow,
} from 'vite-plugin-qiankun/dist/helper'
let instance = null
function render({ container } = {}) {
instance = createApp(App)
instance.use(router)
instance.mount(container ? container.querySelector('#subapp') : '#subapp')
}
// 如何独立运行微应用?
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
console.log('并不是qiankun渲染')
render()
}
renderWithQiankun({
mount(props) {
render(props)
},
bootstrap() {
console.log('%c', 'color:green;', ' ChildOne bootstrap')
},
update() {
console.log('%c', 'color:green;', ' ChildOne update')
},
unmount(props) {
instance.unmount()
instance = null
},
})
子应用App.vue配置一下路由跳转条件以及引入ElementPlus美化一下页面,完整代码:
<template>
<div class="SubAppVue">
<el-menu
style="width: 300px; height: calc(100vh - 60px)"
:default-active="activeIndex"
class="el-menu-demo"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b"
@select="handleSelect"
>
<el-menu-item index="/">子应用Home</el-menu-item>
<el-menu-item index="/about">子应用About</el-menu-item>
</el-menu>
<router-view></router-view>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const activeIndex = ref('/')
const handleSelect = (key, keyPath) => {
router.push({ path: key })
}
</script>
<style>
body {
margin: 0px;
}
.SubAppVue{
display: flex;
}
</style>
最后修改vite.config.js适配主应用配置的端口以及其他qiankun标识,完整代码:
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import qiankun from 'vite-plugin-qiankun'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// https://vite.dev/config/
export default defineConfig({
plugins: [vue(),
qiankun('qiankun-subApp', {
useDevMode: true,
}),
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
server: {
port: 5555,
headers: {
// 重点1: 允许跨域访问子应用页面
'Access-Control-Allow-Origin': '*',
},
},
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
})
这样就完成了基础的主子应用的创建了,如果出现问题,比如报错:
application ‘xxx‘ died in status LOADING_SOURCE_CODE: [qiankun] You need 这时候就需要检查主子应用是不是认定的子应用名称匹配以及检查子应用的Vite.config.js是不是有问题,接下来附上页面成品图:
到这里,基础的页面搭建就结束了,接下来我会继续完善文章,比如:
- qiankun主子应用如何通过pinia进行通信
- qiankun主子应用部署到服务器资源访问异常问题
- qiankun主子应用如何配置动态路由
请持续关注,如果觉着对你有用,不妨动动发财小手点个赞👍,创作不易,如有引用,请务必标明出处。
欢迎各位评论区留言互相交流,谢谢!