找回密码
 会员注册
查看: 25|回复: 0

对巨石应用说不:转转商业微前端qiankun历史项目迁移升级实践

[复制链接]

2万

主题

0

回帖

6万

积分

超级版主

积分
64101
发表于 2024-9-19 23:27:44 | 显示全部楼层 |阅读模式
之前和大家分享过微前端的相关知识(具体可见之前的文章:闲庭信步聊前端-见微知著微前端),本次分享qiankun在转转商业的一些实践,及问题解答背景商业Crm开发多年,随着开发成长为巨石应用。打包慢、升级难、排查问题链路长,同时性能差,用户体验欠缺。加上产品对系统定位思考不合理,常年的堆积功能,系统混乱。对系统的改造迫在眉睫。解决方案通过利用qiankun微前端框架拆分商业Crm,在主应用中不断拆出功能,部署在子应用上,Crm作为主应用(系统基座),加载子应用。在迁移功能到子应用的过程中,完成代码规范和技术栈升级。成果已经成功拆分了部分页面,多系统运行,做到了用户无感知技术升级,替换了原有页面,打包和加载速度有所提升。最重要的是没有耽误正常的业务开发。技术细节引入qiankun框架,主站点使用原生的qiankun包,文档如下:https://qiankun.umijs.org/zh。子应用使用了umi框架,umi提供了乾坤插件,使用方式和原生的qiankun相比使用更简单,同时可以和原生配合使用,文档可见:https://umijs.org/zh-CN/plugins/plugin-qiankunqiankun一共有两种加载子应用的方式1.提前注册,把需要加载的子应用提前写好,包括注入容器,路由匹配规则,子应用入口import { registerMicroApps, start } from 'qiankun';registerMicroApps([  {    name: 'react app', // app name registered    entry: '//localhost:7100',    container: '#yourContainer',    activeRule: '/yourActiveRule',  },  {    name: 'vue app',    entry: { scripts: ['//localhost:7100/main.js'] },    container: '#yourContainer2',    activeRule: '/yourActiveRule2',  },]);start();2.第二种方式loadMicroApp,动态加载子应用。这种方式的好处是可以随时随地,按照业务需求加载子应用方法的属性介绍:name:区分子应用,在拥有多个子应用的时候,name非常重要,用于通信entry:子应用入口,在本地环境和线上环境可能有区别,需要在区分配置。container: 微应用的容器节点的选择器或者Element实例通过initGlobalState,可以实现主应用和子应用的通信。下面介绍我们在系统中的使用细节主站点系统配置安装"qiankun": "2.4.1",将所有需要迁移的路由更改指向,指到专属中转页面,在转转商业Crm中的是component: () => import('@views/Child')在Child.jsx中部署乾坤的加载逻辑import { loadMicroApp, initGlobalState } from 'qiankun';that.microApp = loadMicroApp(  {    name: 'crmtest',    entry: 'https://crm.xxxxxxx.com/childfirst',    container: this.containerRef.current,    props: { authList: this.props.authList }  },  {    getPublicPath: (v) => {      return '//s1.xxxxxxx.com/biz/bizcrmweb_child_first/static/js/';    }  });商业Crm采用的方式是loadMicroApp,这样的好处是非常灵活,加载哪个微应用可以动态配置,可以随时替换。子应用系统配置子应用使用了umi,所以直接使用"@umijs/plugin-qiankun": "2.22.0",这是umi提供的qiankun插件,使用相比原生的qiankun要更简单。安装插件以后,在umi指定的config文件夹下面的config.js开启插件:qiankun: {    slave: {},  },然后在入口文件(通常是app.js)上声明生命周期方法,便于主应用调用。注意:不暴露生命周期会导致系统报错。export const qiankun = {  // 应用加载之前  async bootstrap(props) {    console.log('app1 bootstrap', props)  },  // 应用 render 之前触发  async mount(props) {    console.log('app1 mount', props);    props.onGlobalStateChange((state, prev) => { // state: 变更后的状态; prev 变更前的状态      console.log(state, prev, '子应用收到信息')    })    // props.setGlobalState(state);  },  // 应用卸载之后触发  async unmount(props) {    console.log('app1 unmount', props)  }}配置结束后,启动多个项目,将子应用指到主应用规定的域名地址上,就可以开始调试了。排坑答疑阶段1.子应用还需要有路由配置吗?如何跳转?子应用需要有完整的路由配置,主应用将所有的子应用路由都指到了同一个页面(crm是指到了前面提到的child.jsx),并不区分页面,但是路由的是变化的,如下所示:  [{    path: 'child',    component: () => import('@views/Child'),  }, {    path: 'tools/paper',    component: () => import('@views/Child'),  }, {    path: 'finance/saledetail',    component: () => import('@views/Child')  }]此时子应用的路由系统会启用,根据当前的路由加载不一样的页面进来。2.权限系统是如何运行的?在crm目前的方案中,权限系统是从主应用中注入到子应用中的,每次切换路由,主应用先去加载权限,再加载子应用,保证子应用的权限及时更新。如下:通过props注入进系统import { loadMicroApp, initGlobalState } from 'qiankun';that.microApp = loadMicroApp(  {    name: 'crmtest',    entry: 'https://crm.xxxxxxx.com/childfirst',    container: this.containerRef.current,    props: { authList: this.props.authList }  },  {    getPublicPath: (v) => {      return '//s1.xxxxxxx.com/biz/bizcrmweb_child_first/static/js/';    }  });3.如何保证样式隔离?样式隔离是微前端开发中非常重要的问题。Qiankun在子应用切换的过程中,会自动注销掉上一个应用的样式,这样可以避免微应用之间的干扰。对于父应用和子应用之间的样式干扰,要分情况对待。如果是框架的样式干扰,例如商业Crm有技术栈改进的需求(antd3升级到antd4),可以通过给框架样式加前缀,利用webpack处理,自动转换。对于全局自定义样式有两种处理方法,一种是跟随主应用,子应用就不再配置特别的全局样式。二是加应用前缀,以及CSSmodule,也可以解决问题。4.为什么不开启scopedcss功能解决样式隔离问题?对于Vue框架的系统,开启scopedcss是一个比较省事的解决方案,但是由于React使用合成事件,开启scopedcss会在页面中开启一个shaowdom容器,这个容器会导致冒泡到document上的事件无法触发,所以不能使用。不过React官方已经意识到了这个问题,新版本不再全部冒泡的document上。5.测试环境和线上环境的静态资源配置?如果公司的静态资源没有部署在系统域名下,可以通过入口处的补充属性getPublicPath指定  {    getPublicPath: (v) => {      return '//s1.xxxxxxx.com/static/js/'; // 静态资源链接    }  }6.为什么主应用访问子应用资源会提示跨域?这个问题官方有过回答由于qiankun是通过fetch去获取微应用的引入的静态资源的,所以必须要求这些静态资源支持跨域。如果是自己的脚本,可以通过开发服务端跨域来支持。如果是三方脚本且无法为其添加跨域头,可以将脚本拖到本地,由自己的服务器serve来支持跨域。7.使用umi的qiankun组件为什么会抛出访问不安全的问题?问题如图:如果是在https环境下访问http的资源,就会被umi抛出这个问题。这个问题多半出现在开发阶段,线上部署在同域名下就不会有问题。解决办法是在node_modules搜索这个错误拦截,删除这段安全判断代码。或者将两个站点都改成http访问。8.umi的@umijs/plugin-locale没有提供自定义前缀入参,该如何添加样式前缀?可以把umi的@umijs/plugin-locale组件拷贝出来,自己添加一个前缀属性,然后当作自定义插件使用。结语微前端的概念已经提出来很久了,但是微前端的需要解决的问题还有很多,并不是所有的项目都适合微前端方案。本文分享了微前端的一种实践思路,以及各种具体问题的处理,希望对大家有所帮助。另外,除了目前比较受欢迎的qiankun以外,webpack5推出的模块联邦也是非常不错的方案,大家也可以尝试一下。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-26 12:23 , Processed in 1.711952 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表