微前端(qiankun)搭建 - 新手入门篇

313 阅读3分钟

老大:我们需要像微服务一样搞个微前端

我:好的,www.baidu.com/s?wd=微前端 灵魂吸收天地精华...

... 30分钟后

我:qiankun好像符合老大的需求,这是地址您看看:qiankun.umijs.org/zh

老大:好,尽快实现!

我:又要看文档和写demo了(=_=!!!)

内心:qiankun对于目前市面上不同框架的兼容性、是否可以支持小程序应用、应用之间如何通信、样式隔离怎么处理(balabala...)

怀着忐忑的内心开始了主应用(基座)的搭建

第一步 搭建主应用

vue create qiankun-main

... 10秒钟后

... npm run serve

... 哇!vue的页面好酷炫 !! 不对,我他喵是来学习怎么搭建qiankun基座的~

1.安装qiankun

cnpm i qiankun -S

2.基座 - 微应用基础信息配置

src/micro-app.js

const microApps = [{
    name: 'undefined',
    entry: '//localhost:8888/',
    activeRule: '/undefined',
    container: '#undefined',
    props: {
        routerBase: '/undefined',
        routerList: [{
            path: '/qrCode',
            name: 'qrCode',
            component: 'qrCode'
        }],
        desc: 'undefined一个神奇的前端组织'
    }
}]

export default microApps;

3.基座 - 微应用服务配置

src/micro.js

import { registerMicroApps , start } from 'qiankun'
import microApps from './micro-apps'
/**
 * 
 * @param {Array} microList 微应用列表
 */
export default function (microList) {
    registerMicroApps(microList ?? microApps, {
        // 生命周期 - beforeLoad(连接微应用前调用)
        beforeLoad: app => {
            console.log(`【undefiend组织】预连接${app.name}微应用`)
        },
        // 生命周期 - beforeMount(挂载前调用)
        beforeMount: [
            app => {
                console.log(`【undefiend组织】即将挂载${app.name}微应用`)
            }
        ],
        // 生命周期 - afterMount(挂载后调用)
        afterMount: [
            app => {
                console.log(`【undefiend组织】已经挂载${app.name}微应用`)
            }
        ],
        // 生命周期 - afterUnmount(卸载后调用)
        afterUnmount: [
            app => {
                console.log(`【undefiend组织】已卸载了${app.name}微应用`)
            }
        ]
    });

    // 启动基座服务
    start({
        singular: false,
        sandbox: {
            strictStyleIsolation: true
        }
    });
}

4.基座 - 入口文件配置

App.vue

<template>
  <div id="app">
    <h1>我是基座</h1>
    <!-- undefined是microApps内container对应的id -->
    <div id="undefined"></div>
  </div>
</template>
<script>
  import micro from './micro'
  export default {
    name: 'App',
    created(){
      // 启动微前端
      micro();
    }
  }
</script>

基座 - 笔记

1.1.App.vue内必须有微应用基础信息配置

container: '#undefined'
<div id="undefined"></div>

1.2.路由配置推荐选择history

方便支持路由下发功能

1.3.微应用基础信息配置的props可传所有你想共享给微应用的内容

---------- 美丽的分割线 ---------

5.微应用 - 配置运行时的publicPath

(function() {
    if (window.__POWERED_BY_QIANKUN__) {
      if (process.env.NODE_ENV === 'development') {
        // eslint-disable-next-line no-undef
        __webpack_public_path__ = '//localhost:8888/'
        return;
      }
      // eslint-disable-next-line no-undef
      __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
    }
})();

6.微应用 - webpack配置

vue.config.js

const packageName = require('./package.json').name

module.exports = {
    configureWebpack: {
        output: {
            library: `${packageName}-[name]`,
            libraryTarget: 'umd', // 把子应用打包成 umd 库格式
            jsonpFunction: `webpackJsonp_${packageName}`,
        },
    },
    devServer: {
        port: 8888, // 配置本地代理
        headers: {
            'Access-Control-Allow-Origin': '*' // 解决跨域
        }
    }
}

7.微应用 - 路由基础配置

router/undefiendRouter.js

const undefiendRouter = [{
    path: '/qrCode',
    name: 'qrCode',
    component: () => import('../views/qrCode.vue')
}]

export default undefiendRouter 

8.微应用 - 路由

router/index.js

import Vue from 'vue';
import VueRouter from 'vue-router'
import undefiendRouter from './undefiendRouter'

Vue.use(VueRouter)

const routes = [...undefiendRouter]

const router = new VueRouter({
    base: process.env.BASE_URL,
    routes,
    mode: 'history'
})

export default router

9.微应用 - 入口文件

main.js

import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import routers from './router'
import './public-path'

Vue.config.productionTip = false

// true:一起运行,false:独立运行
const isNotQiankun = !window.__POWERED_BY_QIANKUN__

Vue.config.productionTip = false

let instance = null

// 如果独立运行时,则会执行这里
if (isNotQiankun) render();

/**
 * 微应用初始化
 * @param {Object} props - 主应用传递的参数
 */
function render(props) {
  const {
    container,
    routerBase,
    routerList
  } = props ?? {}
  // 初始化路由
  const router = routerList ? new VueRouter({
    base: routerBase,
    routes: routerList.map(m => {
      return {
        ...m,
        component: () => import(`@/views/${m.component}.vue`)
      }
    }) ?? [],
    mode: 'history'
  }) : routers

  instance = new Vue({
    router,
    render: (h) => h(App)
  }).$mount(container ? container.querySelector('#app') : '#app')
}

/**
 * qiankun 框架子应用的三个生命周期
 * bootstrap 初始化
 * mount 渲染时
 * unmount 卸载
 */

export async function bootstrap(props) {
  console.log('---undefiend---主应用连接中---',props);
}

export async function mount(props) {
  console.log('---undefiend---渲染中---',props);
  render(props)
}

export async function unmount() {
  console.log('---undefiend---卸载中---');
  instance.$destroy()
  instance.$el.innerHTML = ''
  instance = null
}

效果图

12312313.png

下期更新如何进行微前端互相通信 并且微应用依赖于路由下发动态渲染

绝对不咕 (^=^)