Setup Environment
Before getting started, you will need to install Node.js, and ensure that your Node.js version >= 16. We recommend using the LTS version of Node.js 20.
You can check the currently used Node.js version with the following command:
If you do not have Node.js installed in your current environment, or the installed version is too low, you can use nvm or fnm to install the required version.
Here is an example of how to install the Node.js 20 LTS version via nvm:
# Install the long-term support version of Node.js 20
nvm install 20 --lts
# Make the newly installed Node.js 20 as the default version
nvm alias default 20
# Switch to the newly installed Node.js 20
nvm use 20
Step 1: Setup React Applications
Create React Project
You can use create-rsbuild
to create a project with Rsbuild + React. Just execute the following command:
npm create rsbuild@latest
Create App 1
create rsbuild@latest
"Input target folder":
> mfe1
"Select framework":
> React
Create App 2
create rsbuild@latest
"Input target folder":
> mfe2
"Select framework":
> React
Install
Use React in an existing project
To compile React, you need to register the Rsbuild React Plugin. The plugin will automatically add the necessary configuration for React builds.
For example, register in rsbuild.config.ts
:
rsbuild.config.ts
import { defineConfig } from '@rsbuild/core';
import { pluginReact } from '@rsbuild/plugin-react';
export default defineConfig({
plugins: [pluginReact()],
});
Ensure that Webpack version 5 or above is installed by checking the installation report provided by Yarn.
Step 2: Update Entry Files
In both applications, rename the index.js
file to bootstrap.js
. This change allows bootstrap.js
to load asynchronously, which is essential for Module Federation to function correctly between the two applications.
mv src/index.js src/bootstrap.js
Update the contents of bootstrap.js to the following:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>,
);
Now, create a new index.js
file in both applications with the following content to import bootstrap.js
:
Step 3: Create and Expose
Now, create a component to expose from MFE2
3.1 Create Button Component
In MFE2
, create a new file named Button.js
in the src directory with the following content:
import React from 'react';
const Button = () => (
<button>MFE2 Button</button>
);
export default Button;
3.2 Update App.js
Update App.js
in MFE2
to import and render the Button component:
import React from 'react';
import Button from './Button';
function App() {
return (
<div>
<h1>MFE2</h1>
<Button />
</div>
);
}
export default App;
Step 3.3: Configure Rsbuild in MFE2
Create a rsbuild.config.js
file in the root directory of MFE2
with the following configuration:
rsbuild.config.ts
import { defineConfig } from '@rsbuild/core';
import { pluginReact } from '@rsbuild/plugin-react';
import { dependencies } from './package.json';
export default defineConfig({
server: {
port: 3002
},
moduleFederation: {
options: {
name: 'remote',
exposes: {
'./Button': './src/Button',
},
filename: 'remoteEntry.js',
shared: {
...dependencies,
react: {
singleton: true,
requiredVersion: dependencies['react'],
},
'react-dom': {
singleton: true,
requiredVersion: dependencies['react-dom'],
},
},
}
},
plugins: [pluginReact()]
});
Step 4: Consume Remote Module
Consume the exposed module from MFE2
in MFE1
4.1 Update App.js
Update App.js
in MFE1
to import and render the MFE2
Button component:
import React from 'react';
import Button from 'remote/Button'; // federated import
function App() {
return (
<div>
<h1>MFE1</h1>
<Button />
</div>
);
}
export default App;
Step 4.2: Configure Rsbuild in MFE1
Create a rsbuild.config.js
file in the root directory of MFE1
with the following configuration:
rsbuild.config.ts
import { defineConfig } from '@rsbuild/core';
import { pluginReact } from '@rsbuild/plugin-react';
import { dependencies } from './package.json';
export default defineConfig({
server: {
port: 3001
},
moduleFederation: {
options: {
name: 'host',
remotes: {
remote: 'remote@http://localhost:3002/remoteEntry.js',
},
shared: {
...dependencies,
react: {
singleton: true,
requiredVersion: dependencies['react'],
},
'react-dom': {
singleton: true,
requiredVersion: dependencies['react-dom'],
},
},
}
},
plugins: [pluginReact()]
});
This setup initiates Module Federation within MFE1
, and upon initiating the development server, it is accessible at http://localhost:3001
.
Similarly, the configuration activates Module Federation for MFE2
, thereby exposing the Button
component at http://localhost:3002/remoteEntry.js
. With the development server operational, it becomes accessible at http://localhost:3002
.