前言
因为公司的项目都是通过https://xxxx.yyy.cn/[projectName]
等方式部署的,而且不同项目之前有公用模块,需要使用这些公用模块的话,就需要以下几种方式:
- 最简单的方式就是
复制/粘贴
,但其缺点也相当明显,就是模块有修改时需要两边同时修改。 - 通过npm 的方式发包。然后在两个项目中同时引用,但这种方式也有可能在修改的时候忘记在别的项目中更新版本
- 通过webpack ModuleFederation, 模块联邦的方式使用。
尝试使用 ModuleFederation
- Monitor 组件是一个比较正常的页面搜索列表页,这里不列出来了
const Log2 = () => {
return (
<div>123</div>
)
}
const Log3 = () => {
const [count, setCount] = useState(0);
return (
<div onClick={() => setCount(count + 1)}>{count}</div>
)
}
- 刚开始看的时候,还觉得挺简单,只要在设置对应的设置即可
// A项目, 在webpack plugin 中配置如下项目
new ModuleFederationPlugin({
name: 'erp',
filename: 'erp_remoteEntry.js',
// 导出使用的模块
exposes: {
'./Monitor': path.resolve(
__dirname,
'../src/pages/report/monitor/data_monitor/index.page.tsx',
),
'./Log2': path.resolve(
__dirname,
'../src/pages/report/monitor/log2/index.page.tsx',
),
'./Log3': path.resolve(
__dirname,
'../src/pages/report/monitor/log3/index.page.tsx',
),
},
shared: [
{
react: {
singleton: true,
// 这里在我的项目中一定要设置字符串,不能从package.json 直接引过来 dep.react
requiredVersion: '^16.14.0',
},
'react-dom': {
singleton: true,
requiredVersion: '^16.14.0',
},
},
],
}),
// B 项目中使用remote 表示导入远程模块, B项目使用的是umi
// [text](https://umijs.org/docs/max/mf)
const shared = {
react: {
singleton: true,
eager: true,
},
'react-dom': {
singleton: true,
eager: true,
},
};
mf: {
remotes: [
{
// 可选,未配置则使用当前 remotes[].name 字段
aliasName: 'erp',
name: 'erp',
entry: 'https://to.the.remote.com/erp_remoteEntry.js',
},
],
// 配置 MF 共享的模块
shared,
},
一开始在A项目中配置
shared
导致项目build
失败了,因为一开始是通过导入const package = require('./package.json')
然后通过package.dependence['react']
去导入的,后面改成用字符串就成功了因为一开始没有处理
shared
,A项目
与B项目
的react版本问题,导致在B项目
中引用Log3
组件时报错。 处理shared
可以解决
import React from 'react'
const LogPage = React.lazy(() => import('erp/Log3'));
const App = () => {
return (
<React.Suspense fallback={'Loading'}>
<LogPage />
</React.Suspense>
)
}
- 处理了上面的事情后,发现导入
Monitor
组件是有问题的,因为Monitor
页面本身导入了一些翻译内容,比如xx-i18n
包, 并且这个包是通过script
的方式引入的,所以我们需要在B项目中的webpack 中设置externals
在umi
添加plugins
, 在config/config.ts
配置plugin
, plugins: [require('${projectRoot}/xxxplugin')]
, 或者设置headScripts
// ${projectRoot}/plugin.ts
import { IApi } from 'umi';
export default (api: IApi) => {
api.modifyHTML(($) => {
$('head').append([
`<script src='xxx.js'></script>`,
`<script src='others...'></script>`
])
return $;
});
};
- 最后因为
Monitor
引用了A项目中的全局Mobx store
,导致加载失败,最后去除才成功引入。但是后面发现样式有问题,估计是antd
的问题,A 项目中用的是antd4
,B项目用的是antd5
。猜测只要将antd
加入到shared
配置即可,Mobx store
同样