微前端之乾坤实战|技术点评

2,163 阅读2分钟

前言

接入上文,其实乾坤就是singleSpa的一个上层封装(前文链接:singleSpa实战),除了singleSpa的动态引入、应用隔离能力,还原生实现了样式隔离、静态资源接入等效果,话不多说,show me code

正文

既然是微前端,自然有多个前端应用,从而也必然存在一个底盘去承载这些前端应用,那我们先搭建好环境

搭建模拟环境
前置环境
  • vue的基层承载项目
  • react的微应用
开始搭建
  1. 选择一个空文件夹作为根路径
mkdir qiankun-study && cd qiankun-study
  1. 创建qiankun-base(此处用了vue,方便接入UI框架;其实是都可以的)
vue create qiankun-base

如果没有安装vue脚手架,可以执行如下命令进行安装

npm i vue/@cli
  1. 创建vue项目
vue create qiankun-vue
  1. 创建react项目
npx create-react-app qiankun-react
  1. qiankun-base项目中建立路由,此处引入elementUi能稍微好看点儿

注意在main.js中进行引入elementUI

npm i element-ui

main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.config.productionTip = false

Vue.use(ElementUI);
new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

然后改写主页面

# App.vue
<template>
  <div id="app">
    <el-menu :router="true" mode="horizontal">
      <el-menu-item index="/">Home</el-menu-item>
      <el-menu-item index="/vue">Vue应用</el-menu-item>
      <el-menu-item index="/react">React应用</el-menu-item>
    </el-menu>
    // qiankun-base 项目本身的挂载点
    <router-view/>
    // vue应用项目挂载点
    <div id="vue"></div>
   	// react项目挂载点
    <div id="react"></div>
  </div>
</template>

效果如下

image-20210308104043626

此时我们点击另外两个路由是没反应的,很正常,因为还没接入乾坤,回想下singleSpa,我们有挂载点了,自然要进行启动子应用、支持打包成lib并在主应用中进行注册,这些,就是qiankun帮我们做的事情了

进入第二个环节:接入qiankun

接入qiankun

首先,在qiankun-base中接入

引入qiankun
import {
  registerMicroApps,
  start
} from 'qiankun';
定义要注册的子应用
const apps = [
  {
    name: 'vueApp',
    entry: '//localhost:10000',// 默认会加载这个html 解析里面的js 动态的进行执行fetch加载 (所以子应用必须支持跨域)
    container: '#vue',// 容器名
    activeRule: '/vue', // 激活的路径
    props: {
      a: 1
    }

  },
  {
    name: 'reactApp',
    entry: '//localhost:20000',// 默认会加载这个html 解析里面的js 动态的进行执行fetch加载 (所以子应用必须支持跨域)
    container: '#react',// 容器名
    activeRule: '/react' // 激活的路径
  }
]
注册应用并启动
// 注册应用
registerMicroApps(apps);

start({
  prefetch:false // 关闭预加载
}) // 开启qiankun

然后,在子应用中提供支持,主要是根据协议暴露函数、打包格式以及支持跨域

Vue应用

暴露函数
let instance = null;

// 渲染函数
function render() {
  instance = new Vue({
    router,
    render: h => h(App)
  }).$mount('#app');  // 这里是挂载到自己的html中 基座会拿到这个挂载后的html 将其插入进去
}


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


export async function bootstrap() {
  
}

export async function mount(props) {
  render(props)
}

export async function unmount() {
  instance.$destroy();
}
设置打包格式及跨域

根路径下创建vue.config.js文件

module.exports = {
  devServer: {
    port: 10000,
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
  configureWebpack: {
    output: {
      library: `vueApp`, 
      libraryTarget: 'umd',// 把微应用打包成 umd 库格式
    },
  },
}

React应用

暴露函数

import React from 'react';
import ReactDOM, { render } from 'react-dom';
import './index.css';
import App from './App';

function reactRender() {
  ReactDOM.render(
    <React.StrictMode>
      <App />
    </React.StrictMode>,
    document.getElementById('root')
  );
}


if (!window.__POWERED_BY_QIANKUN__) {
  reactRender();
}else {
  
}

export async function bootstrap() {
  
}
export async function unmount() {
  ReactDOM.unmountComponentAtNode( document.getElementById('root') );
}
export async function mount() {
  reactRender();
}


设置打包格式及跨域

首先得先安装一个变线包 : react-app-rewired

npm i react-app-rewired

然后,在项目根路径下(和package.json同级)新建文件config-overrides.js,进行配置覆盖

module.exports = {
    webpack: (config) => {
        config.output.library = 'reactApp';
        config.output.libraryTarget = 'umd';
        config.output.publicPath = 'http://localhost:20000';
        return config;
    },
    devServer: (configFunction) => {
        return function (proxy,allowedHost) {
            const config = configFunction(proxy,allowedHost);
            config.headers = {
                'Access-Control-Allow-Origin': '*'
            }
            return config
        }

    }
}

最后,将所有脚本的react-scripts改写为react-app-rewired

"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-app-rewired eject"
},

至此,我们就完成了qiankun的接入,效果如下

QQ20210308-224542-HD

相关链接

singleSpa实战

微前端之自实现singleSpa

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情