1. 微前端项目架构及选型介绍

1.1. 微前端选型概述

微前端架构是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。考虑到qiankun作为蚂蚁的微前端架构,具备以下特点:①简单。子应用接入像使用接入一个 iframe 系统一样简单,但实际不是 iframe。②能力完备。几乎包含所有构建微前端系统时所需要的基本能力,如样式隔离、js 沙箱、预加载等。③健壮性值得信赖。在蚂蚁内外经受过足够大量的线上系统的考验及打磨。所以,选择qiankun去构建集成应用项目的微前端架构。

1.2. 项目简要

本文配合实战demo讲解微前端项目和集成方案。

【技术选择】

主应用:umi(Ant Design Pro)

子应用:umi(Ant Design Pro)、vue(vue-element-admin)

路由模式:都用hash

【源码地址】
qiankun-demohttps://gitee.com/weihui007/qiankun-demo

2. 微前端基础配置

2.1. 主应用qiankun配置(umi项目)

(1)安装插件

yarn add @umijs/plugin-qiankun -D

 (2)注册子应用

插件构建期配置子应用

export default {qiankun: {master: {apps: [{name: 'reactApp', // 唯一 identry: 'http://localhost:8091', // html entry},{name: 'vueApp',entry: 'http://localhost:8092',},],},},
};

(3)装载子应用

使用路由绑定的方式

export default {routes: [// 配置子应用reactApp关联的路由{name: 'react子应用',path: '/subreact',microApp: 'reactApp',},// 配置子应用vueApp关联的路由{name: 'vue子应用',path: '/subvue',microApp: 'vueApp',},],
};

2.2. 子应用qiankun配置

2.2.1. vue项目

(1)入口文件main.js

子应用需要在自己的入口文件导出 bootstrapmountunmount三个生命周期钩子,以供主应用在适当的时机调用。

bootstrap:只会在子应用初始化的时候调用一次,下次子应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。

mount:应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法。

unmount:应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载子应用的应用实例

// 声明一个变量,可以用于卸载
let instance = null
// 挂载到自己的html中,基座会拿到这个挂载后的html插入进去
function render(props = {}) {const { container } = propsinstance = new Vue({router,store,render: h => h(App)}).$mount(container ? container.querySelector('#app') : '#app')
}// 独立运行
if (!window.__POWERED_BY_QIANKUN__) {render()
}// 子组件的协议,必须暴露三个函数
export async function bootstrap(props) {console.log('bootstrap函数:', props)
}
export async function mount(props) {console.log('mount函数:', props)render(props)
}
export async function unmount(props) {console.log('unmount函数:', props)instance.$destroy()instance = null
}

(2)配置文件vue.config.js

除了代码中暴露出相应的生命周期钩子之外,为了让主应用能正确识别子应用暴露出来的一些信息,子应用的打包工具需要增加如下配置

//修改打包配置
configureWebpack: {output: {//输出暴露的名称,假设名称为vueApplibrary: 'vueApp', //输出暴露的类型libraryTarget: 'umd'}
},
//允许跨域
devServer: {headers: {'Access-Control-Allow-Origin': '*'}
},

2.2.2. react项目(umi项目)

(1)安装 qiankun 插件 @umijs/plugin-qiankun

$ npm i @umijs/plugin-qiankun
# 或者
$ yarn add @umijs/plugin-qiankun

(2)插件注册(config.ts)

export default {qiankun: {slave: {}}
}

(3)配置运行时生命周期钩子(可选)

插件会自动为你创建好 qiankun 子应用需要的生命周期钩子,但是如果你想在生命周期期间加一些自定义逻辑,可以在子应用的 src/app.ts 里导出 qiankun 对象,并实现每一个生命周期钩子,其中钩子函数的入参 props 由主应用自动注入。

export const qiankun = {// 应用加载之前async bootstrap(props) {console.log('bootstrap函数:', props)},// 应用 render 之前触发async mount(props) {console.log('mount函数:', props)},// 应用卸载之后触发async unmount(props) {console.log('unmount函数:', props)}
}

2.3. 主子应用实现通信配置

2.3.1. 主应用umi项目

(1)向umi子应用通信

① 新建src->app.ts文件

import { useState } from 'react';export function useQiankunStateForSlave() {const [projectId, setProjectId] = useState<string>('');return { projectId, setProjectId };
}

② 在组件中使用qiankunStateForSlave

import { useModel } from 'umi';export function ProComp() {const { setProjectId } = useModel('@@qiankunStateForSlave');const onChangePro = () => {setProjectId('123');};return <button onClick={onChangePro}>更改项目信息</button>;
}

(2)向vue子应用通信

① 新建src->action.ts文件

import { initGlobalState } from 'qiankun';const initialState = {// 初始化数据projectId: ''
};// 初始化 state
const actions = initGlobalState(initialState);export default actions;

② 在组件中使用actions

import actions from '@/actions';export function ProComp() {const onChangePro = () => {actions.setGlobalState({ projectId: '123' });};return <button onClick={onChangePro}>更改项目信息</button>;
}

2.3.2. 子应用vue项目

使用qiankun 官方提供的通信方式 - Actions 通信去实现

(1)新建src->actions.js文件

function emptyAction() {//设置一个actions实例// 提示当前使用的是空 Actionconsole.warn('Current execute action is empty!')
}
class Actions {// 默认值为空 Actionactions = {onGlobalStateChange: emptyAction,setGlobalState: emptyAction}/*** 设置 actions*/ setActions(actions) {this.actions = actions}/*** 映射,注册观察者函数,响应 globalState 变化*/ onGlobalStateChange(...args) {return this.actions.onGlobalStateChange(...args)}/*** 映射,设置 globalState*/setGlobalState(...args) {return this.actions.setGlobalState(...args)}
}
const actions = new Actions()
export default actions

(2)入口文件main.js

在mounted的生命周期里注入actions实例

import actions from './actions'
export async function mount(props) {actions.setActions(props) //注入actions实例render(props)
}

(3)使用范例

<template>  <div>  <div>这是子应用</div>  <p>接收到的消息: {{mes}}</p>  <button @click= "btnClick">点击向父应用发送消息</button>  </div>
</template>
<script>
import actions from '../actions'//导入实例
export default {  data() {  return {  mes: '',  }  },  mounted() {  actions.onGlobalStateChange((state) => { //监听全局状态  this.mes = state  }, true);  },  methods:{  btnClick(){  actions.setGlobalState({ info: '123'})//改变全局状态  }  }
}
</script>  

2.3.3. 子应用umi项目

使用useModel钩子函数

import { useModel } from 'umi';function MyPage() {const masterProps = useModel('@@qiankunStateFromMaster');return <div>{JSON.stringify(masterProps)}</div>;
}

3. 微前端项目集成方案

本文利用微前端架构主要实现如下功能:

把不同项目(子应用)集成到一个平台(主应用)。

【顶部导航栏】可包含主应用页面以及各个子应用,子应用可以是任何技术栈(demo中子应用为react和vue)。

【侧边菜单导航栏】可以是主应用页面的子菜单,也可以是子应用的菜单。

【主内容区域】即为页面主要展示区域。若当行了选择的是子应用,即为子应用展示区域。

具体实现效果如下图:

3.1. 主应用改造

主应用为antd pro项目。菜单模式设置为mix(混合菜单),记得切割菜单,即配置splitMenus为true。通过上述配置结合路由配置,即可实现上述平台布局(顶部全局导航+侧边菜单导航混合)。

路由数据结构(routes.ts)参考如下:

export default [{name: '欢迎', // 主应用页面1,在顶部全局导航展示path: '/welcome',icon: 'smile',component: './Welcome',},{name: '管理页', // 主应用页面2,在顶部全局导航展示path: '/admin',icon: 'crown',access: 'canAdmin',component: './Admin',routes: [ // 二级菜单,在侧边菜单导航展示{name: '二级管理页',path: '/admin/sub-page',icon: 'smile',component: './Welcome',},],},{name: 'react子应用', // 子应用1,在顶部全局导航展示path: '/subreact',microApp: 'reactApp',routes: [ // 子应用1的菜单,在侧边菜单导航展示{name: 'Welcome',icon: 'smile',path: '/subreact/Welcome',},],},{name: 'vue子应用', // 子应用2,在顶部全局导航展示path: '/subvue',microApp: 'vueApp',routes: [ // 子应用2的菜单,在侧边菜单导航展示{name: 'Example',icon: 'table',path: '/subvue/example',routes: [{name: 'Table',icon: 'table',path: '/subvue/example/table',},],},],},
];

3.2. 子应用改造

根据window.__POWERED_BY_QIANKUN__判断子应用是不是从qiankun运行环境进来的,进行两套环境改造。如果独立运行,则走原来的逻辑,否则需要走改造后的逻辑。

3.2.1. 布局改造

如果子应用是从qiankun运行环境进入,即window.__POWERED_BY_QIANKUN__为true,则去除子应用头部和导航菜单布局。

umi子应用:删除掉所有的自带界面,将ProLayout布局组件设置pure为true。

vue子应用(vue-element-admin): 用条件语句v-if、v-else判断,如果是qiankun环境,则只保留主内容区域。

3.2.2. 登录逻辑改造

登录权限打通,主应用登录后,切换到子应用不需要再进行登录校验,实现免登录功能。

比如主应用是通过cookie验证用户登录的,当子应用是从qiankun环境进入,则通过对应的cookie判断是否有登录,若已登录则跳过登录直接进入对应页面,若没登录或者登录失效则传值给父应用告诉父应用需要重新登录,然后父应用跳转登录页(可在响应拦截中进行父子应用通讯,实现接口回传token失效等原因告诉父应用需要跳转登录页)。

3.2.3. 其它改造

(1)子应用为vue项目需要判断qiankun环境把路由加上前缀

一般需要修改2个地方:①路由表加上前缀;②路由守卫判断如果没有前缀需加上前缀(用于子应用内部需要做路由跳转)

TIPS:前缀指在主应用中跳转子应用设定的path值。

①参考如下:

如果是qiankun环境,则给路由数据的path(路径)和redirect(重定向)值加上前缀。这样就可以和主应用项目对应的菜单导航栏的跳转路径保持一致。

if (window.__POWERED_BY_QIANKUN__) {routesData.map(item => {if (item.path.includes('/')) {item.path = '/subvue' + item.path}if (item.redirect) {item.redirect = '/subvue' + item.redirect}return item})
}

②参考如下:

如果是qiankun环境,则通过路由守卫 beforeEach对路由跳转前进行判断拦截,如果,跳转的地址没有加有前缀,则加上。否则,会出现404找不到页面。

if (window.__POWERED_BY_QIANKUN__) {router.beforeEach((to, from, next) => {if (!to.path.includes('subvue')) {next({path: '/subvue' + to.path,query: to.query})} else {next()}})
}

(2)其它

除上述提到的,可以根据自身业务需求进行一些改造,常见的有网络请求封装改造、菜单按钮展示改造以及资源加载路径改造等等。

4. 应用集成逻辑图

仅以umi版本为例,展示如下

【推荐文章】

antd pro项目使用qiankun,loading加载页不消失https://blog.csdn.net/w544924116/article/details/120164997antd pro(ProLayout) mix混合菜单不生效https://blog.csdn.net/w544924116/article/details/120211891Error: Module “xxx“ does not exist in container. / antd pro v5启用qiankun报错 / 同时使用mfsu和qiankun报错https://blog.csdn.net/w544924116/article/details/120123331引用window自定义变量以及ts在window上自定义变量数据类型报错的解决方案https://blog.csdn.net/w544924116/article/details/120251686

感谢您读完本文!如果本文对您有帮助,请点个赞呗,您的点赞是对我最大的支持和认可!

我的公众号:大前端教程,欢迎关注,会定期更新前端知识,希望能帮到您。

微前端系列讲解--应用集成方案(qiankun+umi+vue)相关推荐

  1. 微前端实际应用:iframe、qiankun

    目录 1.iframe 1-1 iframe基本理解 1-2 无界方案 1-3 使用无界 1-4 实现细节 1-5 无界微前端框架总结 2.qiankun 2-1 微前端知识温故 2-2 qianku ...

  2. 微前端在得物客服域的实践/那么多微前端框架,为啥我们选Qiankun + MF

    一.业务背景 当前客服一站式工作台包含在线服务.电话.工单和工具类四大功能,页面的基本结构如下: 每个业务模块相对独立,各有独立的业务体系,单个模块体积较大,项目整体采用SPA + iframe的架构 ...

  3. 【微前端】1443- 将微前端做到极致-无界方案

    微前端已经是一个非常成熟的领域了,但开发者不管采用哪个现有方案,在适配成本.样式隔离.运行性能.页面白屏.子应用通信.子应用保活.多应用激活.vite 框架支持.应用共享等用户核心诉求都或存在问题,或 ...

  4. qiankun微前端:script xxxxxx replaced by qiankun或script xxxxxxxxxx replaced by import-html-entry

    qiankun微前端 1.问题:script xxxxxx replaced by qiankun或script xxxxxxxxxx replaced by import-html-entry 2. ...

  5. 将微前端做到极致-无界方案

    大厂技术  高级前端  Node进阶 点击上方 程序员成长指北,关注公众号 回复1,加入高级Node交流群 无界框架已经开源

  6. 基于微前端的大型中台项目融合方案

    点击上方"程序员成长指北"关注 关于微前端是什么,以及微前端落地方案,社区遍地都是,本篇文章不会再赘述这些基础知识.当然如果你没了解过上述知识,也可以直接读下这篇文章,足够浅显易懂 ...

  7. jsp给前端注入值失败_基于 qiankun 的微前端最佳实践(图文并茂) 应用间通信篇...

    引言 大家好~ 本文是基于 qiankun 的微前端最佳实践系列文章之 应用间通信篇,本文将分享在 qiankun 中如何进行应用间通信. 在开始介绍 qiankun 的应用通信之前,我们需要先了解微 ...

  8. qiankun微前端应用间通信实现

    转自基于 qiankun 的微前端最佳实践(图文并茂) - 应用间通信篇 - 掘金本系列其他文章计划一到两个月内完成,点个 关注 不迷路. 本文是基于 qiankun 的微前端最佳实践系列文章之 应用 ...

  9. 基于 qiankun 的微前端最佳实践(万字长文) - 从 0 到 1 篇

    写在开头 微前端系列文章: 基于 qiankun 的微前端最佳实践(万字长文) - 从 0 到 1 篇 基于 qiankun 的微前端最佳实践(图文并茂) - 应用间通信篇 万字长文+图文并茂+全面解 ...

最新文章

  1. HTML5语义化标签综合基础案例,HTML5语义化标签综合案例
  2. 皮一皮:这年头,没看过火影还没法做医生了...
  3. activemenu怎么拼 vue_Vue-el-menu使用,点击按钮跳转指定页面
  4. Description Resource Path Location Type Java compiler level does not match the version of the instal
  5. 用django2.1开发公司官网(上)
  6. linux 指令引用变量,Linux之变量引用与命令替换
  7. 云原生人物志|Pulsar翟佳:社区的信任最重要
  8. 怎么查看oracle中sys的密码修改,oracle sys 密码修改
  9. Mybatis入门程序
  10. 从word得到表格数据插入数据库(6位行业代码)
  11. BST:Transformer在推荐领域的应用
  12. javascript:void(0)的作用示例
  13. 视频抽帧并存图 python_使用Python实现跳帧截取视频帧
  14. 思维导图哪款好用?怎么借助MindManager 做旅游计划
  15. windows 搭建HTTP文件服务器(Nginx 方式)
  16. 机器学习(统计学习方法)基础知识
  17. Selenium2_如何判断WebElement元素对象是否存在
  18. 如何生成PSSM矩阵
  19. RGSSAD解密程序(基于RgssadUnpacker改进以支持RGSS3A)
  20. Kfc点餐系统 小程序

热门文章

  1. 智慧城市物联网主要技术路线
  2. #6279. 数列分块入门 3
  3. 1分钟学会PS背景虚化
  4. Git学习笔记之时光穿梭机
  5. 位置定位(LocationManager)
  6. bezier.CSS_SVG_canvas画_贝兹曲线
  7. 百度网盘如何生成目录树结构?
  8. 基于java的简单英雄联盟胜率计算
  9. Mac os x 的一些小技巧
  10. java中算术异常值_依据拉依达准则来剔除异常值程序