qiankun+vue2+vue3+umi微前端集成开发落地实践

1,668 阅读1分钟

qiankun虽然有官方文档说明,但由于各种包版本不同,可参考的文档并不完善。以下基于几种框架进行开发实践,选择react作为主应用,接入子项目vue2(前后端不分离)、vue3、antdesignpro(umi)。

主应用

react-create-app生成的react18项目为例,搭配react-router-dom 6.x

  1. 安装 qiankun:
$ yarn add qiankun # 或者 npm i qiankun -S
  1. 注册微应用并启动:
  • 基于路由配置
import { registerMicroApps, start } from 'qiankun';
registerMicroApps([{
  name: 'aaa',
  entry: process.env.NODE_ENV == 'production'?'/vue2App/':'//localhost:8066',
  container: '#container',
  activeRule: '/vue2',
  props: {...}
}, {
  name: 'bbb',
  entry: process.env.NODE_ENV == 'production'?'/vue3App/':'//localhost:8077',
  container: '#container',
  activeRule: '/vue3',
  props: {...}
}]);
start();

name需保持唯一,当微应用信息注册完之后,一旦浏览器的url发生变化,便会自动触发qiankun的匹配逻辑,所有activeRule规则匹配上的微应用就会append到指定的container中,同时依次调用微应用暴露出的生命周期钩子。

如果微应用不是直接跟路由关联时,可选择手动加载微应用的方式。

  • 手动加载微应用
import { loadMicroApp } from 'qiankun';
loadMicroApp({
    name: 'ccc',
    container: '#container',
    entry: process.env.NODE_ENV == 'production'?'/umiApp/':'//localhost:8099'
})
  1. webpack配置:原有写在微应用中devServer.proxy接口代理均需迁移至主应用
  2. nginx配置:
server {
    listen       80;
    server_name  localhost;
    access_log /export/Logs/access.log main;
    error_log  /export/Logs/error.log warn;
    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';
    if ($request_method = 'OPTIONS') {
        return 204;
    }
    location / {
        try_files $uri $uri/ /index.html;
	root /export/App/dist/ ;
    }
    location /vue2App/ {
        rewrite ^/vue2App/(.*)$ /$1 break;
        proxy_pass http://vue2.xx.com;
    }
    location /vue3App/ {
        rewrite ^/vue3App/(.*)$ /$1 break;
        proxy_pass http://vue3.xx.com;
    }
    location /umiApp/ {
        rewrite ^/umiApp/(.*)$ /$1 break;
        proxy_pass http://umi.xx.com;
    }
    proxy_redirect     off;
    proxy_set_header   X-Real-IP            $remote_addr;
    proxy_set_header   X-Forwarded-For      $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto    $scheme;
}

微应用

vue2微应用

vue-cli 3+ 生成vue 2.xwebpack4构建项目为例

  1. src目录新增public-path.js:
if (window.__POWERED_BY_QIANKUN__) {
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
  1. 入口文件main.js修改
  • 导入public-path.js需放在入口文件最顶部 。
  • 建议使用history模式的路由,base设置的值必须与注册时activeRule保持一致。
import './public-path';
import Vue from 'vue';
import App from './App';
import routes from '@/router/index.js';
import VueRouter from 'vue-router';
import store from '@/store';

let router = null;
let instance = null;
function render(props = {}) {
  const { container } = props;
  Vue.use(VueRouter)
  router = new VueRouter({
    base: window.__POWERED_BY_QIANKUN__ ? '/vue2/' : '/',
    mode: 'history',
    routes,
  });
  instance = new Vue({
    store,
    router,
    template: '<App/>',
    components: { App }
  }).$mount(container ? container.querySelector('#app') : '#app');
}
// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
  render();
}
export async function bootstrap(props) {
  console.log(props);
}
export async function mount(props) {
  render(props);
}
export async function unmount() {
  instance.$destroy();
  instance.$el.innerHTML = '';
  instance = null;
  router = null;
}
  1. 打包配置:
  • output.publicPath 在生产环境路径必须要与注册时entry保持一致
// wepack.base.conf.js
const { name } =  require('./package.json');
module.exports = {
  output: {
    library: name,
    libraryTarget: 'umd',
    jsonpFunction: `webpackJsonp_${name}`,
    publicPath: process.env.NODE_ENV === 'production'?'/vue2App/':'/'
  }
}
// webpack.dev.conf.js
module.exports = {
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Cache-Control': 'no-cache'
    }
  }
}

vue3微应用

vue-cli 4+ 生成vue 3.xwebpack5构建项目为例

  1. src目录新增public-path.js:
if (window.__POWERED_BY_QIANKUN__) {
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
  1. 入口文件main.js修改
  • 导入public-path.js需放在入口文件最顶部 。
  • 建议使用history模式的路由,base设置的值必须与注册时activeRule保持一致。
import './public-path';
import { createApp } from 'vue';
import App from './App.vue';
import ElementPlus from 'element-plus';
import { createRouter, createWebHistory } from 'vue-router';
import routes from './router';

let router = null;
let instance = null;
let history = null;
function render(props = {}) {
    const { container } = props;
    history = createWebHistory(window.__POWERED_BY_QIANKUN__ ? '/vue3' : '');
    router = createRouter({
        history,
        routes
    })
    instance = createApp(App);
    instance.use(router).use(ElementPlus);
    instance.mount(container ? container.querySelector('#app') : '#app');
}
// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
    render();
}
export async function bootstrap(props) {
    console.log(props);
}
export async function mount(props) {
    render(props);
}
export async function unmount() {
    instance.unmount();
    instance._container.innerHTML = '';
    instance = null;
    router = null;
    history.destroy();
}
  1. 打包配置(vue.config.js):
  • publicPath 在生产环境路径必须要与注册时entry保持一致
const { defineConfig } = require('@vue/cli-service');
const { name } =  require('./package.json');
module.exports = defineConfig({
  transpileDependencies: true,
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Cache-Control': 'no-cache'
    }
  },
  publicPath: './',
  // 上下两种方式均可
  // publicPath: process.env.NODE_ENV === 'production'?'/vue3App/':'/',
  configureWebpack: {
    output: {
      library: name,
      libraryTarget: 'umd',
      chunkLoadingGlobal: `webpackJsonp_${name}`,
    }
  }
})
  1. nginx配置:
server {
    listen       80;
    server_name  localhost;
    access_log /export/Logs/access.log main;
    error_log  /export/Logs/error.log warn;

    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';

    if ($request_method = 'OPTIONS') {
        return 204;
    }
    location / {
        try_files $uri $uri/ /index.html;
	root /export/App/dist/ ;
        add_header Cache-Control no-cache;
    }
    proxy_redirect     off;
    proxy_set_header   X-Real-IP            $remote_addr;
    proxy_set_header   X-Forwarded-For      $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto    $scheme;
}

umi3微应用

ant-design/pro-cli 2+生成 umi 3.xwebpack5构建项目为例

  1. 安装qiankun
npm install @umijs/plugin-qiankun
  1. 入口文件app.jsx修改
export const qiankun = {
  async bootstrap(props) {
    console.log'app1 bootstrap', props)
  },
  async mount(props) {
    console.log('app1 mount', props);
  },
  async unmount(props) {
    console.log('app1 unmount', props);
  },
};
  1. 配置qiankun开启(config.js):
  • base设置的值建议与手动加载微应用时路由保持一致。
  • publicPath 在生产环境路径必须要与注册时entry保持一致
export default {
    qiankun: {
        slave: {}
    },
    devServer: {
        headers: {
          'Access-Control-Allow-Origin': '*'
        }
    },
    base: '/rms',
    publicPath: process.env.NODE_ENV === 'production' ? '/umiApp/' : '/',
}
  1. nginx配置同上