VUE项目如何使用qiankun搭建微前端架构

最近,在做前端微应用时候用到了qiankun 框架,因此对使用中遇到的问题做了总结。

微前端其实就是:一个完整应用划分成一个主应用和一个或多个微应用,应用间相互独立,可相互通信。

qiankun的官方文档:https://qiankun.umijs.org/zh/api

当主应用是 hash 模式时,一般微应用也是 hash 模式。主应用的一级 hash 路径会分配给对应的微应用(比如 #/base1 ),此时微应用如果需要在 base 路径的基础上进行 hash 模式下的二级路径跳转(比如 #/base1/child1 ),这个场景在当前 VueRouter 的实现方式下需要自己手动实现,给所有路由都添加一个前缀即可。VueRouter 的 hash 模式下的 base 参数不支持添加 hash 路径 base。

一:使用history 模式(qiankun官方也是介绍的history模式)

    ① 对主应用进行改造即 安装使用qiankun   

        主应用项目必须安装 qiankun:npm i qiankun -S

        在主应用的src文件夹下新建一个 micros 文件夹,在micros文件夹新建index.js、app.js

   1.index.js —— 主要是导出方法及生命周期钩子,用于在主应用中注册微应用 


import {
  registerMicroApps,
  addGlobalUncaughtErrorHandler,
  start
} from 'qiankun'// 微应用注册信息
import apps from './app'

// (1)registerMicroApps:包含两个参数,第一个参数是微应用的一些注册信息,第二个参数是全局的微应用生命周期钩子。:
// (2)addGlobalUncaughtErrorHandler:全局的未捕获异常处理器,微应用发生报错的时候亦可以用这个api捕捉。
// (3)start:我们用来启动qiankun的方法,包含一个参数,具体的参数用途不再详述。
registerMicroApps(apps, {
  beforeLoad: (app) => {
    console.log('before load=====', app.name)
    return Promise.resolve()
  },
  afterMount: (app) => {
    console.log('after mount=====', app.name)
    return Promise.resolve()
  }
})

addGlobalUncaughtErrorHandler((event) => {
  console.error(event)
  const { message: msg } = event
  if (msg && msg.includes('died in status LOADING_SOURCE_CODE')) {
    console.error('微应用加载失败,请检查应用是否可运行')
  }
})

export default start

   2.app.js —— 主要是写一些微应用的信息

/*
 * @Author: karson 
 * @Date: 2021-09-10 16:04:57 
 * @Last Modified by:  karson 
 * @Last Modified time: 2021-09-10 16:04:57 
 */
const apps = [
  {
    name: 'micro-app-plugin',
    entry: '//localhost:8088',
    container: '#plugin-container',
    activeRule: '/micplugin'
  }
]

// 导出的是registerMicroApps的第一个参数,是一个对象数组,其中数组每个字段的作用如下:
// (1)name:微应用的名称,后面改造微应用的时候一定要与这个name对应
// (2)entry:微应用运行的域名加端口,我用的是本地8088端口
// (3)container:启动微应用需要一个dom容器,里面就是这个dom容器的 id
// (4)activeRule:触发启动微应用的规则,当检测到url中含有activeRule的值时,将启动微应用



export default apps

3.在主应用中添加微应用 dom 容器

VUE项目如何使用qiankun搭建微前端架构

 4、main.js 改造  —— 主要就是导入 start 方法,然后运行,启动qiankun

......
import start from '@/micros'

......
start()

②微应用改造 (微应用不需要额外安装任何其他依赖即可接入 qiankun 主应用。)

   1.导出相应的生命周期钩子

    改造子应用main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import '@/assets/main.css'
Vue.config.productionTip = false

// 新增:用于保存vue实例
let instance = null; 

// 新增:动态设置 webpack publicPath,防止资源加载出错
if (window.__POWERED_BY_QIANKUN__) {  
  // eslint-disable-next-line no-undef  
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
/** * 新增: * 渲染函数 * 两种情况:主应用生命周期钩子中运行 / 微应用单独启动时运行 */
function render() {  
  // 挂载应用  
  instance = new Vue({    
    router,    
    store,    
    render: (h) => h(App),  
  }).$mount("#micro-app-child");}

// #micro-app-child   对应子应用public中index.html 对应的容器id
/** 
* 新增: 
* bootstrap 只会在微应用初始化的时候调用一次,
  下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。 
* 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。 
*/
export async function bootstrap() {  
  console.log("VueMicroApp bootstraped");
}
/** 
* 新增: 
* 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法 
*/
export async function mount(props) {  
  console.log("VueMicroApp mount", props);  
  render(props);
}
/** 
* 新增: 
* 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例 
*/
export async function unmount() {  
  console.log("VueMicroApp unmount");  
  instance.$destroy();  
  instance = null;
}
// 新增:独立运行时,直接挂载应用
if (!window.__POWERED_BY_QIANKUN__) {  
  render();
}

2.改造子应用webpack  (vue.config.js)

const path = require("path");

module.exports = {
  devServer: {
    // 监听端口
    port: 8088,
    // 关闭主机检查,使微应用可以被 fetch
    disableHostCheck: true,
    // 配置跨域请求头,解决开发环境的跨域问题
    headers: {
      "Access-Control-Allow-Origin": "*",
    },
  },
  configureWebpack: {
    resolve: {
      alias: {
        "@": path.resolve(__dirname, "src"),
      },
    },
    output: {
      // 微应用的包名,这里与主应用中注册的微应用名称一致
      library: "micro-app-plugin",

      // 将你的 library 暴露为所有的模块定义下都可运行的方式
      libraryTarget: "umd",

      // 按需加载相关,设置为 webpackJsonp_MicroAppPlugin 即可
      jsonpFunction: `webpackJsonp_micro-app-plugin`,
    },
  },
};

3.改造子应用路由

const router = new VueRouter({
  mode: 'history',
  base: window.__POWERED_BY_QIANKUN__ ? '/micplugin' : '/',
  routes,
  scrollBehavior(to, from, savedPosition) { //设置滚动行为
    ......
  }
})

二:使用hash模式 (与history模式一样,做如下修改)

    1.主应用micros下app.js  改造

/*
 * @Author: karson
 * @Date: 2021-09-10 16:04:57
 * @Last Modified by:   karson
 * @Last Modified time: 2021-09-10 16:04:57
 */
const apps = [
  {
    name: 'micro-app-plugin',
    entry: '//localhost:8088',
    container: '#plugin-container',
    activeRule: '#/micplugin'
  }
]

// 导出的是registerMicroApps的第一个参数,是一个对象数组,其中数组每个字段的作用如下:
// (1)name:微应用的名称,后面改造微应用的时候一定要与这个name对应
// (2)entry:微应用运行的域名加端口,我用的是本地8088端口
// (3)container:启动微应用需要一个dom容器,里面就是这个dom容器的 id
// (4)activeRule:触发启动微应用的规则,当检测到url中含有activeRule的值时,将启动微应用


export default apps

 2.子应用路由改造

let prefix = '';
if(window.__POWERED_BY_QIANKUN__){
  prefix = '/micplugin' // /micplugin为主应用的activeRule
}

const routes: Array<RouteConfig> = [
  {
    path: prefix+'/',
    name: 'home',
    component: Home
  },
  {
    path: prefix+'/about',
    name: 'About',
    component: About
  }
]
const router = new VueRouter({
  mode: 'hash',
  routes
});

// 这里主要是适配子应用的单独访问和继承访问
if(window.__POWERED_BY_QIANKUN__){
  router.beforeEach((to, from, next) => { 
    if(!to.path.includes('/micplugin')){   //  /micplugin为主应用的activeRule
      next({path: prefix+to.path})
    }else{next()}
  })
}

 

上一篇:浅析qiankun主应用与微应用间如何通信解决微应用需要重复登录的问题


下一篇:浅析VUE项目如何使用qiankun搭建微前端架构