目录

2024-07-17-微前端框架之乾坤qiankun-vue3viteqiankun手把手搭建版

微前端框架之乾坤【qiankun】 vue3+vite+qiankun(手把手搭建版)

前言

简介:qiankun是一种微前端框架,可以将多个前端应用集成为一个整体。每个子应用可以使用不同的框架和技术栈,它们之间可以相互独立开发和部署,qiankun提供了一套完整的生命周期函数和通信机制,可以让不同的子应用之间进行跨框架和跨域的通信和交互

具体查看官网:

业务场景

描述图:

https://i-blog.csdnimg.cn/direct/635703d543c448b6a8064bb296fcf3a3.png#pic_center

描述:

base 基础框架为主应用,包括左侧菜单部分,顶部头部部份,也是qiankun中主应用。

子应用:wms,wcs…等应用在右侧展示区展示

关联: 通过点击左侧菜单加载对应的子应用页面

乾坤的使用(主应用和子应用)

主应用配置

1,安装依赖

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

$ yarn add vite-plugin-qiankun 或者 npm i vite-plugin-qiankun -S

$ yarn add vite-plugin-qiankun/dist/helper 或者npm i vite-plugin-qiankun/dist/helper -S

2,main.ts配置

关键代码:

import apps from './qiankun.js'
import { registerMicroApps, addGlobalUncaughtErrorHandler } from 'qiankun'

// 注册微应用
registerMicroApps(apps, {
  beforeLoad: () => console.log('before load'),
  beforeMount: [() => console.log('before mount')],
  afterMount: () => console.log('*********'),
  beforeUnmount: () => console.log('****beforeUnmount *****'),
  afterUnmount: () => console.log('-------afterUnmount *********---')
})

// 全局的未捕获异常处理器
addGlobalUncaughtErrorHandler(event => {
  console.log(event)
})

registerMicroApps:注册子应用信息的api

addGlobalUncaughtErrorHandler :捕获qiankun 运行时的异常错误信息

详见文档:

qiankun.js: 自定义子应用注册时的一些信息

3,qianjun.js 文件

关键代码:

import actions from './actions'
const microApps = [
  {
    name: 'wmsApp',
    entry: '/baseWms/', //本地http://localhost:9002:baseWms
    activeRule: '/wms'
  }
  // {
  //   name: 'app-vue1',
  //   entry: '//localhost:8003/app-vue1/',
  //   activeRule: '/app-vue1'
  // }
]
const apps = microApps.map(app => {
  return {
    ...app,
    container: '#app-micro',
    props: {
      routerBase: app.activeRule, // 下发基础路由
      temmpData: { name: '小强', age: 25 },
      parentActions: actions
    },
    loader(loading) {
      console.log('loading', loading)
    }
  }
})
export default apps

1,name:子应用的命名,

2,entry 子应用进入的地址,通过 配合 activeRule触发进入

注意点:这个 名字可以随便填写,生成环境nginx 配置必须一致

3,activeRule 触发子应用的标识,在这里,得注意 不能和entry 相同,否则会出现进入子应用刷新后覆盖父应用bug

4, container 子应用触发后,内容挂载区域,我这里定义id 等于app-micro,此文件自定义为qiankun.vue(后面会在路由配置一块详细描述)

5,props :父应用向子应用传参(可以传自定义参数,也可以传父应用中qiankun相关函数)这里我将主应用的相关qiankun 全局监听函数写在了action.js类

4,action.js 文件

关键代码:

 import { initGlobalState } from 'qiankun'
// import { useRouter, useRoute } from 'vue-router'
import router from './router/index'
const state = {
  // num: 1,
  // name: 'codeFirst'
}
// 初始化 state
const actions = initGlobalState(state)
actions.onGlobalStateChange((state, prev) => {
  console.log('主应用检测到state变更父级', state)
  console.log('主应用检测到state变更父级', router)
  // let {goParent:true} = state
  // let url = state.url.replace('/wms/', '')
  router.push(state.url)
})
// 你还可以定义一个获取state的方法下发到子应用
// actions.getGlobalState = function () {
//   return state
// }
export default actions

initGlobalState:定义全局状态,并返回通信方法,建议在主应用使用,微应用通过 props 获取通信方法。

onGlobalStateChange:用来监听全局状态,主要监听子应用传什么给父应用,父应用需要做什么操作,此代码是子应用传了url 通知父应用进行跳转

具体看官网

5,router.js 文件

关键代码1:

// qiankunWindow.__POWERED_BY_QIANKUN__ ? '/wms/' :
const base = '/'
console.log(baseRoutes, 'baseRoutes*********************')
const router = createRouter({
  history: createWebHistory(base), //createWebHashHistory() hash模式
  routes: baseRoutes
})

https://i-blog.csdnimg.cn/direct/d1dddf9c90ae440699a60a9390ab1aac.png

注意点:

1,使用 qiankun 路由方式必须改为 createWebHistory

2,qiankunWindow.__POWERED_BY_QIANKUN__是可以用来判断qiankun是否启用

3,实时注册路由的时候,把push 改为 replace 之前测试时出现浏览器前进后退地址返回问题

6,base.js 文件

关键代码:

  //更改后的
  {
    path: '/wms/:pathMatch(.*)*',
    component: () => import('@/views/qiankun.vue'),
    meta: { title: 'xxx', icon: 'icon-home' }
  },

结合第3部分 qiankun.js,有个activeRule触发条件,这里我使用/wms 作为触发子应用的 标识,然后通过配置路由跳转到qiankun.vue 文件

之后如果加了子应用 wcs, 也可以配置对应的activeRule跳转到qiankun.vue 文件,其它子应用配置一样

7,qiankun.vue 文件

关键代码:

<script lang="ts">
import { defineComponent, reactive } from 'vue'
import { start } from 'qiankun'
import { useRouter, useRoute } from 'vue-router'
export default defineComponent({
  setup() {
    return reactive({
      path: useRoute().path,
      microApp: '' as any
    })
  },
  created() {},
  deactivated() {
    window.qiankunStarted = false
  },
  async mounted() {
    if (!window.qiankunStarted) {
      window.qiankunStarted = true
      start()
    } else {
      const router = useRouter()
      const route = useRoute()
    }
  },
  activated() {},
  updated() {},

  methods: {
    // restartQianKun() {
    //   window.qiankunStarted = true
    //   console.log('我刚进来了乾坤1111')
    //   start()
    // },
    // startQianKun() {
    //   if (!window.qiankunStarted) {
    //     console.log('我刚进来了乾坤')
    //     this.restartQianKun()
    //   }
    // }
  }
})
</script>
<template>
  <div id="app-micro"></div>
</template>

start:是 qiankun自带的api ,主要是开启qiankun

在进入页面的时候,首先判断qiankun是否开启,没有开启则开启

注意点 window.qiankunStarted = false 写在页面离开的生命周期自己写的一个处理,看过很多资料,qiankun没有手动关闭,自己内部会处理,此处可以不加

div的是元素挂载区域,与第3部分中 container 对应

8,vite.config.ts文件

注意点:

https://i-blog.csdnimg.cn/direct/b4bf8cbbb9f84560afcd7b83b4345431.png

这段代码 必须加上,不然本次本地跑不起来,发布到线上主应用也打不开

子应用配置

1,安装依赖

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

$ yarn add vite-plugin-qiankun 或者 npm i vite-plugin-qiankun -S

$ yarn add vite-plugin-qiankun/dist/helper 或者npm i vite-plugin-qiankun/dist/helper -S

2,main.ts配置

关键代码:

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

import { renderWithQiankun, qiankunWindow, QiankunProps } from 'vite-plugin-qiankun/dist/helper'
let app
function render(props = {}) {
  console.log(props, 'props-----------')
  const { container, routerBase = '/wms' } = props
  // const router = createRouter({
  //   routes,
  //   history: createWebHistory()
  // })
  app = createApp(App)
  // app.use(store).use(router).mount('#child')
  app
    .use(store)
    .use(router)
    .mount(container ? container : '#child')
  app.config.globalProperties.parentActions = props.parentActions
  //app.use(store).mount(container ? container : '#child')
}

function qianKunControll() {
  renderWithQiankun({
    bootstrap() {
      console.log('888888888----')
    },
    mount(props) {
      // actions.actions.setGlobalState({
      //   parentActions: props
      // })

      console.log(props, 'props----123')
      render(props)
    },
    unmount() {
      app.unmount()
      app = null
    },
    update: function (props: QiankunProps): void | Promise<void> {
      console.log('woshi chilid upadte----')
    }
  })
}
if (qiankunWindow.__POWERED_BY_QIANKUN__) {
  qianKunControll()
}

if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
  render()
  console.log('独立运行')
}

renderWithQiankun: 加载qiankun的生命周期,必须添加,否则子应用与父应用直接无法正常运行通信,其中

mount生命周期用来加载父应用传过来的参数并挂载渲染

unmount:这个生命周期用来处理每次挂载在父应用容器中的页面元素,每次子应用离开进行卸载

bootstrap: 初始化子应用 很少用

update:子应用更新改变 很少用

render 函数用来渲染子应用

props 就是父应用传过来的 props 具体看主应用的 qiankun.js文件

如果主应用 传来props 证明qiankun状态中,则子应用挂载在父应用,否则子应用独立运行挂载在自己的index.html div容器中

app.config.globalProperties.parentActions = props.parentActions 主要将父应用的qiankun全局监听函数保存起来,作用是在任何地方使用父应用中监听函数,从而通知父应用。可以理解为qiankun 的父子通信。

2,router下面index.js

https://i-blog.csdnimg.cn/direct/81e0aed259354f78a25fd9c8aa6443b7.png

细节问题:base 路径必须和 父应用qiankun.js 中activeRule 一致,否则跑起来各种问题,这里我理解为 通过根据访问的域名地址,去找对应的资源地址,比如 127.0.0.1/wms/index 会找wms下面的资源

引入 的qiankunwindow 是用来判断是否为qiankun状态从而进行逻辑判断 ,此次没有用到

3,vite.config.js

https://i-blog.csdnimg.cn/direct/da60369eefac4faf9742abf79007488d.png

注意点:

本地开发环境中 base 改为 ./ 生产必须改成 和 父应用 entry一致 这里是 baseWms

https://i-blog.csdnimg.cn/direct/7c25a95e92304c7fb722e04ed2c9afd9.png

注意点:

这里必须加上,qiankun会解析,并且第一个参数的名称必须和 父应用 qiankun.js中name 一致

部署部分(待补充)

1,nginx

关键代码:

        location / {
            root   E:\\微前端\\base-project\\dist;
            index  index.html /index.htm;
            try_files $uri $uri/ /index.html;
        }
        location /wms {
            # root   E:\\微前端\\base-project\\dist\\baseWms;
            # index  index.html /index.htm;
            # try_files $uri $uri/ /index.html;
            proxy_pass   http://127.0.0.1:8091;
        }
  server {
        listen       8091;
        server_name  127.0.0.1; 
        location / {
            root   E:\\微前端\\base-project\\dist\\baseWms;
            index  index.html /index.htm;
            try_files $uri $uri/ /index.html;
        }
    }

1,目前出现过的问题,主应用和子应用跳转正常,但是跳转结束后,刷新 404 ,解决办法,使用: proxy_pass http://127.0.0.1:8091;进行跳转

2,目前还未解决遇到的 问题,正常直接访问子应用 属于独立访问,那么不会启动qiankun,此时其实父应用和子应用ip一致,无法加载父应用base基础数据,解决思路,nginx中父子应用都独立配置相同ip不同端口,比如 127.0.0.1:9001 和127.0.0.1:9002

3,其它问题,比如样式隔离,数据共享资源问题,等等可能存在的问题(暂时未出现)

qiankun使用总结:

1,基于 single-spa 封装了更加开箱即用的api

2,与技术栈无关可以vue react angular 等框架一起使用

3,样式隔离 (目前一个主,和一个子没问题)

4,js沙箱(目前一个主,和一个子没问题)

5,提供完整的父子通信api和数据共享模式,也可以通过路由传参,缓存等方式进行数据共享

6, 子应用静态资源预加载 只需在start中配置 prefetch (具体看文档)

使用问题:

1,如果有多个子应用,乾坤会一次加载,所以只要拥有一个子应用配置错误,乾坤启动失败

68747470733a2f2f62:6c6f672e6373646e2e6e65742f6d305f35313430303934382f:61727469636c652f64657461696c732f313430343338393435