qiankun + vue3.0基座 + vue2.0微应用

926 阅读4分钟

最近在做qiankun项目搭建工作,遇到了一些坑和大家一起分享一下,如有写得不对的或者不好的地方,希望大家指点。这边讲的是在路由页面里面添加子应用容器,任意切换主子应用页面

  1. 首先创建一个vue3.0的项目 vue create qiankun-app,版本要选择vue3.0作为基座使用,创建项目的时候最好把路由也一并选上
  2. 在main.js中写入
import { createApp } from 'vue'
import App from './App.vue'
import router from './router';
 
createApp(App)
.use(router)
.mount('#base-app');

这边要注意的是app.vue和index.html里面的id也要是base-app 3. 在项目根目录下新建vue.config.js,添加内容如下

const { defineConfig } = require('@vue/cli-service')
 
module.exports = defineConfig({
    transpileDependencies: true,
    devServer: {
    // 可以在配置中 配置端口 VUE_APP_PORT = 8080
    port: 8080,
    headers: {
        'Access-Control-Allow-Origin': '*' // 允许跨域访问子应用页面
    }
    },
})
  1. 创建子应用 vue create qiankun-vue-child,这边需要使用vue2.0,如何搭建省略
  2. 添加路由
const router = createRouter({
// 有些时候希望直接启动微应用从而更方便的开发调试,你可以使用这个全局变量来区分当前是否运行在 qiankun 的主应用的上下文中
    base: window.__POWERED_BY_QIANKUN__ ? '/vue' : '/', 
    history: createWebHistory(), 
    routes
})

这边需要注意的是base对应主应用里面路由激活规则activeRule的路径

7.在main.js中引入路由,内容如下

import { createApp } from 'vue'
import App from './App.vue'
import router from './router`';`
 
function render (props = {}) {
const { container } = props
createApp(App)
.use(router)
.mount(container ? container.querySelector('#app') : '#app'); 
// 为了避免根id#app与其他DOM冲突,需要限制查找范围
}
  1. 在项目根目录下新建vue.config.js,添加内容如下
const { defineConfig } = require('@vue/cli-service')
const packageName = require('./package.json').name;
 
module.exports = defineConfig({
    transpileDependencies: true,
    devServer: {
        port: 8083, // 重点6
        headers: { // 重点7:同重点1,允许子应用跨域
            'Access-Control-Allow-Origin': '*'
        }
    },
    configureWebpack: {
    output: {
        library: `${packageName}-[name]`,
        libraryTarget: 'umd', // 把子应用打包成 umd 库格式
        //  jsonpFunction: `webpackJsonp_${packageName}`
        chunkLoadingGlobal: `webpackJsonp_${packageName}`
        }
    }
})
  1. 准备好这些之后 在主应用中 安装乾坤 npm i qiankun -S
  2. 在主应用入口文件src/main.js中注册子应用
import { registerMicroApps, start } from 'qiankun'
 
import { createApp } from 'vue'
import App from './App.vue'
import router from './router';
 
<!--  import qiankun  -->
import { registerMicroApps, start } from 'qiankun'
 
// 在主应用中注册子应用
registerMicroApps([{
    name: 'vue app', // 微应用的名称 要求唯一
    entry: '//localhost:8083',  // 通俗理解就是(微应用的访问地址)
    container: '#vue',  // 微应用挂载到主应用上的容器
    activeRule: '/vue', // 微应用激活条件
}]
)
 
createApp(App)
.use(router)
.mount('#base-app');
  1. 子应用需要在src目录新增public-path.js,然后在main.js中引入
if (window.__POWERED_BY_QIANKUN__) {
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__ + 'vue/' // +后面的内容是有配置publicPath的时候需要使用,没有配置可以不用写
}
  1. 子应用的main.js需要修改为
import { createApp } from 'vue'
import App from './App.vue'
import router from './router';
 
function render (props = {}) {
    const { container } = props
    createApp(App)
    .use(router)
    .mount(container ? container.querySelector('#app') : '#app'); // 为了避免根id#app与其他DOM冲突,需要限制查找范围
}
 
if (!window.__POWERED_BY_QIANKUN__) {
    render()
}
 
 
/**
* bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
* 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
*/
export async function bootstrap() {
    console.log('react app bootstraped');
}
 
/**
* 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
*/
export async function mount(props) {
    // ReactDOM.render(<App />, props.container ? props.container.querySelector('#root') : document.getElementById('root'));

    console.log('乾坤子应用容器加载完成,开始渲染 child')
    console.log('props from main mount', props)
    render(props)
}
 
/**
* 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
*/
export async function unmount() {
 
}
 
 
/**
* 可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效
*/
export async function update(props) {
    console.log('update props', props);
}

13.主应用在需要使用到微应用的组件位置添加容器<div id="vue" /> 对应配置的container,在mounted函数里面启动,代码如下:

onMounted(() => {
    if (!window.qiankunStart) {
        window.qiankunStart = true;
        start({
          sandbox: { strictStyleIsolation: true } // 开启沙箱严格模式 防止主应用的样式污染到微应用
        });
    }
});
  1. 13点需要注意,有时候多个微应用切换的时候会显示白屏,这时候一定是路由的问题,一定要往路由这边去排查问题
  2. 微应用内部使用keepalive是可以正常使用的,跨应用的时候keepalive是没有用的,需要保持输入框的内容能够缓存住,可以使用本地缓存的方式,在vue的声明周期函数中去存储和删除。这个是个人的看法,有什么更好的想法欢迎交流。
  3. 希望大家的qiankun学习没有那么多的坑相伴。