1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 微前端系列讲解--应用集成方案(qiankun+umi+vue)

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

时间:2023-06-17 10:01:52

相关推荐

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

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-demo/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

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

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

$npmi@umijs/plugin-qiankun# 或者$yarnadd@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: ''};// 初始化 stateconst 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>importactionsfrom'../actions'//导入实例exportdefault{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加载页不消失/w544924116/article/details/14997antd pro(ProLayout) mix混合菜单不生效/w544924116/article/details/11891Error: Module “xxx“ does not exist in container. / antd pro v5启用qiankun报错 / 同时使用mfsu和qiankun报错/w544924116/article/details/13331引用window自定义变量以及ts在window上自定义变量数据类型报错的解决方案/w544924116/article/details/120251686

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

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。