Skip to content

qiankun基础与应用

概念

qiankun是蚂蚁金融科技基于 single-spa 的微前端实现库. 提供了更加开箱即用的API, 接入简单(类似于iframe一样简单)并且实现了css样式隔离与js沙箱机制.

运行时动态加载, 主子应用完全结偶, 采用协议API接入(子应用必须导出 bootstrap, mount, unmount方法)

TIP

qiankun 只确保子应用之间样式隔离,主应用跟子应用之间的样式冲突需要手动解决,主应用可以通过设置 prefixCls 的方式避免冲突. 参考issue

实现思路(同single-spa)

将一个应用划分成若干个子应用, 将子应用打包成一个个的lib, 当路径切换时加载不同的子应用, 这样子应用都是独立的, 技术栈也不用做限制了, 解决了前端协调开发问题

使用流程

qiankun接入参考文档

主应用(Vue)

yarn add qiankun

js
// main.js
import { registerMicroApps, start } from 'qiankun'
// 子应用配置
let apps = [
  {
    name: 'vue-project1', // 名称
    entry: '//localhost:8081', // 入口 【也可以使用/path 再nginx路由转发】
    container: '#vue-project1', // 挂载自应用的容器(此id在父元素中定义)
    activeRule: '/vue-project1', // 激活的路由规则【给single-spa使用】
    props: {
      msg: `hellow, vue-project1, I'm your father.` // 传递给子应用的props,子应用通过三个协议API可获取
    }
  },
  {
    name: 'vue-project2',
    entry: '//localhost:8082',
    container: '#vue-project2',
    activeRule: '/vue-project2',
    props: {
      msg: `hellow, vue-project2, I'm your father.`
    }
  },
  {
    name: 'vue-project3',
    entry: '//localhost:8083',
    container: '#vue-project3',
    activeRule: '/vue-project3',
    props: {
      msg: `hellow, vue-project3, I'm your father.`
    }
  }
]

// 注册子应用, 可以配置生命周期:https://qiankun.umijs.org/zh/api#registermicroappsapps-lifecycles
registerMicroApps(apps, {
  beforeLoad: (app) => console.log('beforeLoad: ', app.name)
})
// 启动&配置:https://qiankun.umijs.org/zh/api#startopts
start({
  // prefetch: true
})

子应用

在入口文件暴露三个qiankun协议的API函数

main.js配置

js
// main.js
let instance = null

function render(props) {
  Vue.config.productionTip = false
  instance = new Vue({
    router,
    render: function (h) {
      return h(App)
    }
  }).$mount('#app') // 【不能与基座应用冲突!】挂载到自己的容器中. 基座应用会获取整个html插入
}

// 判断是否作为【独立应用】渲染 https://qiankun.umijs.org/zh/faq#%E5%A6%82%E4%BD%95%E7%8B%AC%E7%AB%8B%E8%BF%90%E8%A1%8C%E5%BE%AE%E5%BA%94%E7%94%A8%EF%BC%9F
if (!window.__POWERED_BY_QIANKUN__) {
  render()
} else {
  // 作为子应用时,需要动态配置webpack的publicPath,以获取static文件
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

// 乾坤子应用协议必须导出的三个API
// props可用于主-子应用通信
export async function bootstrap(props) {} // 启动

// 挂载
export async function mount(props) {
  console.log('vue-project1接收到props:', props)
  render(props)
}

// 卸载
export async function unmount(props) {
  instance.$destroy()
}

路由判断

js
// router/index.js
const router = new VueRouter({
  mode: 'history',
  base: window.__POWERED_BY_QIANKUN__ ? '/vue-project1' : './',
  routes
})

打包成lib&允许跨域配置

js
// vue.config.js
module.exports = {
  devServer: {
    host: 'localhost',
    port: '8081',
    // 配置应用可被get请求跨域访问
    headers:{
      'Access-Control-Allow-Origin': '*'
    }
  },
  // 配置打包成lib库
  configureWebpack: {
    output: {
      library: 'vue-project1', // 包名称
      libraryTarget: 'umd', // 包规范
      jsonpFunction: 'webpackJsonp_child-app-name' // 防止渲染冲突
    }
  }
}

TIP

jsonpFunction:webpack默认将懒加载的模块存储在webpackJsonp的数组中。当多个项目使用webpack构建,都会push在这一个数组中,假如webpack需要执行入口模块(chunk-vendors),则会执行多个chunk-vendors, 造成渲染冲突.【不过有js沙箱隔离,貌似不配置这个也没啥问题】 webpack文档