UMI 中使用qiankun问题记录
背景:基座应用使用的umi,子应用没有使用umi,但也是使用react。
Umi 文档:https://umijs.org/docs/max/micro-frontend#route
按照官方文档配置,记录一些问题, 以及全部配置
目录
-
- 问题
-
- 一、如何传值
- 二、loading状态变更
- 三、样式隔离
-
-
- 1、当父子应用的html的字体大小不一样,导致子应用rem的字体大小跟随父应用的html字体来,
-
- 四、子应用中window.open 处理
-
-
- 问题
- 解决
-
- 五、子应用中`<iframe> `处理
-
-
- 问题
-
- 六、跨域问题
- 全部配置
-
- 一、父应用(基座应用)
-
- 1、config.ts或者.umirc.ts
- 2、在app.tsx导出qiankun配置
- 3、组件和路由配置
- 4、子系统中的代理,父系统要重新定义
- 二、子应用
-
- 1、在src下新增一个文件public-path.js
- 2、修改配置文件
- 3、 在入口文件src/index.tsx 中加入
- 4、跳转处理
- 5、路由处理
- 其他问题
问题
一、如何传值
1、onGlobalStateChange
传值方式,需要二次触发state变动才行。
我们的应用是登录获取用户信息后,才加载子应用,然后传值, 在mount中拿不到值,需要二次触发变更才行
// 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
export async function mount(props) {console.log('mounted', props);// 方式一: 这个首次触发不执行, 要第二次触发才行props.onGlobalStateChange((state, prev) => {// state: 变更后的状态; prev 变更前的状态console.log('子应用', state, prev);});// 子应用渲染initRender(props);
}
2、umi传函数,获取一个全局变量。(当前情况使用该方式)
// 基座应用 app.ts
let initInfo = {};
export const qiankun = {apps: [{name: 'aurora',entry: 'http://localhost:3000/', // process.env.OLD_SYS_HOST// container: '#aurora',activeRule: '/aurora',props: {getUserInfo: () => initInfo,},},],
}
// 一些api调用获取信息
api().then(res => initInfo = res)// 子应用, 直接调用函数获取
export async function mount(props) {console.log('mounted', props.getUserInfo());
}
二、loading状态变更
根据官网的配置,无论是自定义加载动画还是使用autoSetLoading
, 发现loading状态一直返回true。
我们需要在afterMoute时设置为false,我们手动执行这步
// 在基座应用新增子应用生命钩子配置
export const qiankun = {apps: [],lifeCycles: {// 配置生命钩子,用于loading,umi提供的子应用加载动画有问题,不会结束async afterMount(props) {console.log('挂载完');// 发现props中有个setLoading函数,执行props.props.setLoading(false); },async afterUpdate(props) {console.log('更新')}},
};
如果使用 autoSetLoading
, 可以在global.less 中修改loading的样式。
// qiankun 子应用loading的样式修改,这里使用的是route配置microAppProps下autoSetLoading
.qiankun-micro-app-wrapper {.ant-spin-spinning {margin-top: calc(50vh - 16Px);.ant-spin-dot {font-size: 32Px;i {width: 14Px;height: 14Px;}}}
}
三、样式隔离
将父应用或者子应用的样式加前缀
使用antd框架:
// webpack配置
{loader: 'less-loader',options: {lessOptions:{modifyVars: {// @ant-prefix是自定义antd组件类名前缀的,需要配合<ConfigProvider prefixCls="gap-ant">使用"@ant-prefix": "gap-ant",},}},
}// 入口jsx
<ConfigProvider prefixCls="gap-ant">
有些文档说message和modal需要单独修改, 但实践发现Modal已经被修改了,message没有,可能是版本更新了
message.config({top: 100,duration: 2,maxCount: 3,prefixCls: 'gap-ant-message', // 注意messge自己定义的前缀 需要加上 -message
});
Modal.config({rootPrefixCls: 'gap-ant',
})
如果是用的element框架,使用插件替换:
1、使用change-prefix-loader替换js中的class前缀
2、使用postcss-change-css-prefix替换css样式前缀
参考: https://blog.csdn.net/shanghai597/article/details/133884670
如果是自定义的样式,没有统一的前缀, 就不能使用这种方法了
问题记录: postcss-change-css-prefix 导致echarts的包冲突了,项目无法启动。
直接复制源码代码,当做自定义插件配置:
const postcss = require('postcss');const replaceStr = (str, prefix, replace) => {const reg = new RegExp(`(^|(\\s)+|\\.|=)${prefix}(?!icon)`, 'g');return str.replace(reg, `$1${replace}`);
};module.exports = postcss.plugin('class-prefix', function (opts = {}) {const { prefix = 'ant-',