之前和大家分享过微前端的相关知识(具体可见之前的文章:闲庭信步聊前端 - 见微知著微前端),本次分享qiankun在转转商业的一些实践,及问题解答
背景
商业Crm开发多年,随着开发成长为巨石应用。打包慢、升级难、排查问题链路长,同时性能差,用户体验欠缺。加上产品对系统定位思考不合理,常年的堆积功能,系统混乱。对系统的改造迫在眉睫。
解决方案
通过利用qiankun微前端框架拆分商业Crm,在主应用中不断拆出功能,部署在子应用上,Crm作为主应用(系统基座),加载子应用。在迁移功能到子应用的过程中,完成代码规范和技术栈升级。
成果
已经成功拆分了部分页面,多系统运行,做到了用户无感知技术升级,替换了原有页面,打包和加载速度有所提升。最重要的是没有耽误正常的业务开发。
技术细节
引入qiankun框架,主站点使用原生的qiankun包,文档如下:
qiankun.umijs.org/zh。
子应用使用了umi框架,umi提供了乾坤插件,使用方式和原生的qiankun相比使用更简单,同时可以和原生配合使用,文档可见:
umijs.org/zh-CN/plugi…
qiankun一共有两种加载子应用的方式
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处理,自动转换。
对于全局自定义样式有两种处理方法,一种是跟随主应用,子应用就不再配置特别的全局样式。
二是加应用前缀,以及CSS module,也可以解决问题。
4.为什么不开启 scoped css 功能解决样式隔离问题?
对于Vue框架的系统,开启 scoped css 是一个比较省事的解决方案,但是由于React使用合成事件,开启 scoped css 会在页面中开启一个shaow dom容器,这个容器会导致冒泡到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推出的模块联邦也是非常不错的方案,大家也可以尝试一下。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!