|
之前和大家分享过微前端的相关知识(具体可见之前的文章:闲庭信步聊前端-见微知著微前端),本次分享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推出的模块联邦也是非常不错的方案,大家也可以尝试一下。
|
|