qiankun 微前端接入(vue 2.0 + react 17实践)

1,296 阅读2分钟

何为乾坤

image.png

In Chinese, qian(乾) means heaven and kun(坤) earth. qiankun is the universe.

用作者的话说,它是一个宇宙

这是一个vue的基础项目(vue2.0 + webpack)

image.png

这是一个react的基础项目

image.png

qiankun所做的就是把,这两个项目整一起,且流畅(iframe一点都不流畅)

上手

安装 (这里父应用添加就行)

$ yarn add qiankun # 或者 npm i qiankun -S

1.接入方式:

1.1:根据路由匹配加载

入口js配置,这里对应vue文件的main.js

import { registerMicroApps, start } from 'qiankun'

const getActiveRule = (hash) => (location) => location.hash.startsWith(hash)

registerMicroApps([
  {
    name: 'react app', // app name registered
    entry: '//localhost:3001',
    container: '#react_app',
    // 这里路由用的hash模式
    activeRule: getActiveRule('#/qiankunChild'),
  }
]
)

start()

在app.vue中增加子应用容器

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <div id="react_app"></div>
    <router-view/>
  </div>
</template>

地址栏输入vue项目的端口,增加匹配后的地址qiankunChild

image.png

成功加载

image.png

1.2:手动加载

import { loadMicroApp } from 'qiankun';


loadMicroApp({
  name: 'app',
  entry: '//localhost:3001',
  container: '#qiankunChild',
});

html部分

<h2 @click="showChild">接入 react app</h2>
<div class="child-content" id="qiankunChild"></div>

js部分

    showChild () {
      loadMicroApp({
        name: 'app',
        entry: '//localhost:3001',
        container: '#qiankunChild'
      })
    }

image.png

点击后(这里直接在html元素下方增加的子应用)

image.png

好像成了,又好像没成,这里图片为啥没显示出来,F12一下瞅瞅

image.png 可以看到这个svg图的路径是父应用的 然而父应用没有这张图

image.png

这是什么原因呢 查看官方demo这里直接用了base64

image.png

照着来一遍,使用base64替换原导入方案

image.png 这样就ok了

2.微应用改造

通过主应用简单的安装后,子应用已经可以接入,但是只是简单的显示,后续还需要对子应用进行改造
未改造前: 主应用打开f12会提示(需要在app的入口导出生命周期)

image.png

2.1改造第一步:微应用增加生命周期

这里需要在微应用的入口js增加导出bootstrapmountunmount三个生命周期函数,(update为可选生命周期) 供主应用在必要时调用,这里直接在react根目录下index.js中添加

/**
 * bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
 * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
 */
 export async function bootstrap() {
  console.log('react app bootstraped')
}

/**
 * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
 */
export async function mount(props) {
  console.log('mount')
  // ReactDOM.render(<App />, props.container ? props.container.querySelector('#root') : document.getElementById('root'))
}

/**
 * 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
 */
export async function unmount(props) {
  console.log('unmount')
  // ReactDOM.unmountComponentAtNode(
  //   props.container ? props.container.querySelector('#root') : document.getElementById('root'),
  // )
}

/**
 * 可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效
 */
export async function update(props) {
  console.log('from parent app', props)
}


在每个周期加点log

2.2改造第二步,修改打包配置

(这里针对react 17应用,其他项目官方文档有说明)

step1:

在 src 目录新增 public-path.js

if (window.__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

step3:

安装插件 @rescripts/cli

npm i -D @rescripts/cli

step3:

根目录新增 .rescriptsrc.js

const { name } = require('./package');


module.exports = {
  webpack: (config) => {
    config.output.library = `${name}-[name]`;
    config.output.libraryTarget = 'umd';
    // 这里好像版本不匹配,注释
    //config.output.jsonpFunction = `webpackJsonp_${name}`;
    config.output.globalObject = 'window';

    return config;
  },


  devServer: (_) => {
    const config = _;

    config.headers = {
      'Access-Control-Allow-Origin': '*',
    };
    config.historyApiFallback = true;
    config.hot = false;
    // 这里好像版本不匹配,注释
    //config.watchContentBase = false;
    config.liveReload = false;

    return config;
  },
};

qiankun与微前端

主应用引入qiankun并且改造微应用后,即可正常使用qiankun

这边记录几个微应用比较关心的问题

1.子父应用如何通信

方式1:localStorage、window

传统方式,不做解释

方式2:使用postmessage

传统方式,不做解释

方式3:父应用手动加载子应用

父传子
调用子应用生命周期的update方法

showChild () {
  this.micriAppInstance = loadMicroApp({
    name: 'app',
    entry: '//localhost:3001',
    container: '#qiankunChild'
  })
},
postValue () {
  this.micriAppInstance.update({'message': 'hellow'})
}

image.png

控制台可以看到父应用向子应用传的参数,调用了之前暴露的update方法。

子传父 初始化应用时使用props增加回调函数传参

  • props - object - 可选,初始化时需要传递给微应用的数据。

父应用传参

  this.micriAppInstance = loadMicroApp({
    name: 'app',
    entry: '//localhost:3001',
    container: '#qiankunChild',
    // 增加子应用回调函数
    props: {
      childCallback: (message) =>{
        console.log(message)
      }
    }
  })

子应用处理,这里mount生命周期可以获取到父应用传来的回调方法

export async function mount(props) {
  props.childCallback && props.childCallback({'message': 'hellow , big app'})
}

可以将childCallback,绑定到子应用全局上,这样所有页面都可以调用 image.png

2.如何预加载资源

prefetchApps,见官方文档

3.样式隔离

sandbox,文档中搜索

写在最后

本文仅针对vue和react项目对qiankun进行初体验,更多内容请戳官方文档 qiankun.umijs.org/zh