Nx Monorepo React与标准React(CRA)的模块联邦配置
在Nx React远程应用中暴露组件给非Nx标准React应用(模块联邦方案)
一、Nx React 远程应用配置
1. 调整Webpack配置
在Nx远程应用的apps/[remote-app-name]/webpack.config.js中添加模块联邦配置:
const { composePlugins, withNx } = require('@nrwl/webpack'); const { withReact } = require('@nrwl/react'); const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin'); module.exports = composePlugins(withNx(), withReact(), (config) => { // 注册模块联邦插件 config.plugins.push( new ModuleFederationPlugin({ name: 'nxRemote', // 远程应用标识,宿主端需对应 filename: 'remoteEntry.js', // 暴露的入口文件名 exposes: { // 配置要暴露的组件路径,键名是宿主端引用的路径 './Button': './apps/remote-app/src/lib/Button.tsx', './Card': './apps/remote-app/src/lib/Card.tsx', }, // 共享依赖,避免重复加载React核心库 shared: { react: { singleton: true, requiredVersion: '^18.2.0' }, 'react-dom': { singleton: true, requiredVersion: '^18.2.0' }, }, }) ); // 设置远程应用的公共访问路径(需与启动地址一致) config.output.publicPath = 'http://localhost:4201/'; return config; });
2. 拆分应用入口
修改远程应用的src/main.tsx,改为延迟加载入口文件:
import('./bootstrap');
创建src/bootstrap.tsx作为实际运行入口:
import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './app/app'; ReactDOM.createRoot(document.getElementById('root')!).render( <React.StrictMode> <App /> </React.StrictMode> );
3. 启动远程应用
指定端口启动,确保与publicPath配置一致:
nx serve remote-app --port 4201
二、非Nx标准React宿主应用配置
以Create React App创建的应用为例,使用Craco修改Webpack配置:
1. 安装依赖
npm install @craco/craco --save-dev
2. 配置Craco
在项目根目录创建craco.config.js:
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin'); module.exports = { webpack: { plugins: { add: [ new ModuleFederationPlugin({ name: 'reactHost', // 关联远程应用,格式为「远程应用标识@远程应用地址/remoteEntry.js」 remotes: { nxRemote: 'nxRemote@http://localhost:4201/remoteEntry.js', }, // 共享依赖需与远程端版本一致 shared: { react: { singleton: true, requiredVersion: '^18.2.0' }, 'react-dom': { singleton: true, requiredVersion: '^18.2.0' }, }, }), ], }, configure: (webpackConfig) => { // 修改入口为bootstrap文件,确保模块联邦加载完成后再渲染 webpackConfig.entry = './src/bootstrap'; return webpackConfig; }, }, };
3. 调整项目入口
修改package.json的启动脚本:
"scripts": { "start": "craco start", // 其他脚本... }
创建src/bootstrap.tsx作为入口文件:
import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; ReactDOM.createRoot(document.getElementById('root')!).render( <React.StrictMode> <App /> </React.StrictMode> );
4. 引入并使用远程组件
在src/App.tsx中通过懒加载引入远程组件:
import React, { lazy, Suspense } from 'react'; // 按照远程端exposes的键名引入 const RemoteButton = lazy(() => import('nxRemote/Button')); const RemoteCard = lazy(() => import('nxRemote/Card')); function App() { return ( <div className="App"> <h1>非Nx React宿主应用</h1> <Suspense fallback={<div>加载远程组件中...</div>}> <RemoteButton label="来自Nx远程的按钮" /> <RemoteCard title="Nx远程卡片内容" /> </Suspense> </div> ); } export default App;
5. 启动宿主应用
npm start
三、常见问题排查
- 依赖版本冲突:确保两端React、ReactDOM版本完全匹配,shared配置中的
requiredVersion需准确对应 - publicPath错误:远程应用的publicPath必须是可直接访问的完整URL,不能使用相对路径
- Nx配置覆盖:检查Nx默认Webpack配置是否与自定义配置冲突,确保
composePlugins正确合并插件 - 组件导出问题:远程组件需使用默认导出,或确保宿主端import路径与远程端
exposes的键名完全匹配
内容的提问来源于stack exchange,提问作者Phucq.ins
相关产品推荐
相关产品推荐

