# Basic CRA with Rsbuild :::tip Demo Reference Check out the example project list here: [Rsbuild CRA](https://github.com/module-federation/module-federation-examples/tree/master/cra) ::: ## Setup Environment Before getting started, you will need to install [Node.js](https://nodejs.org/), 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: ```bash node -v ``` If you do not have Node.js installed in your current environment, or the installed version is too low, you can use [nvm](https://github.com/nvm-sh/nvm) or [fnm](https://github.com/Schniz/fnm) to install the required version. Here is an example of how to install the Node.js 20 LTS version via nvm: ```bash # 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: ```sh [npm] npm create rsbuild@latest ``` ```sh [yarn] yarn create rsbuild ``` ```sh [pnpm] pnpm create rsbuild@latest ``` ```sh [bun] bun create rsbuild@latest ``` #
### Create App 1 ```bash create rsbuild@latest "Input target folder": > mfe1 "Select framework": > React "Select language": > TypeScript ``` ### Create App 2 ```bash create rsbuild@latest "Input target folder": > mfe2 "Select framework": > React "Select language": > TypeScript ``` ### Install ```bash cd mfe1 pnpm i ``` ```bash cd mfe2 pnpm i ```
### Use React in an existing project To compile React, you need to register the Rsbuild [React Plugin](https://rsbuild.dev/plugins/list/plugin-react). The plugin will automatically add the necessary configuration for React builds. For example, register in `rsbuild.config.ts`: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginReact } from '@rsbuild/plugin-react'; export default defineConfig({ plugins: [pluginReact()], }); ``` :::tip For projects using Create React App, you can refer to the [CRA Migration Guide](https://rsbuild.dev/guide/migration/cra). ::: Ensure that Webpack version 5 or above is installed by checking the installation report provided by Yarn. ## Step 2: Installing Module Federation Build Plugin ```bash pnpm add @module-federation/enhanced pnpm add @module-federation/rsbuild-plugin --save-dev ``` ## Step 3: 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. ```bash mv src/index.tsx src/bootstrap.tsx ``` Update the contents of bootstrap.tsx to the following: ```typescript 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.tsx` file in both applications with the following content to import `bootstrap.tsx`: ```typescript import('./bootstrap'); ``` ## Step 4: Create and Expose Now, create a component to expose from `MFE2`
### 4.1 Create Button Component In `MFE2`, create a new file named `Button.tsx` in the src directory with the following content: ```typescript const Button = () => ( <button>MFE2 Button</button> ); export default Button; ``` ### 4.2 Update App.tsx Update `App.tsx` in `MFE2` to import and render the Button component: ```typescript import './App.css'; import Button from './Button'; const App = () => { return ( <div className="content"> <h1>MFE2</h1> <Button /> </div> ); }; export default App; ```
## Step 5: Configure Rsbuild in MFE2 First create `module-federation.config.ts` in file in the root directory of `MFE2` with the following configuration: ```ts title="module-federation.config.ts" import { createModuleFederationConfig } from '@module-federation/rsbuild-plugin'; export default createModuleFederationConfig({ name: 'remote', exposes: { './Button': './src/Button', }, filename: 'remoteEntry.js', shared: { ...dependencies, react: { singleton: true, }, 'react-dom': { singleton: true, }, }, }); ``` And then modify the `rsbuild.config.ts` file in the root directory of `MFE2` with the following configuration: ```diff title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginReact } from '@rsbuild/plugin-react'; + import { pluginModuleFederation } from '@module-federation/rsbuild-plugin'; + import mfConfig from './module-federation.config'; export default defineConfig({ server: { port: 3002 }, plugins: [ pluginReact() + pluginModuleFederation(mfConfig) ] }); ``` ## Step 6: Consume Remote Module Consume the exposed module from `MFE2` in `MFE1`
### 6.1 Update App.tsx Update `App.tsx` in `MFE1` to import and render the `MFE2` Button component: ```typescript import React from 'react'; import Button from 'remote/Button'; // federated import function App() { return ( <div> <h1>MFE1</h1> <Button /> </div> ); } export default App; ``` ### Step 6.2: Configure Rsbuild in MFE1 First create `module-federation.config.ts` in file in the root directory of `MFE1` with the following configuration: ```ts title="module-federation.config.ts" import { createModuleFederationConfig } from '@module-federation/rsbuild-plugin'; export default createModuleFederationConfig({ name: 'host', remotes: { remote: 'remote@http://localhost:3002/remoteEntry.js', }, shared: { react: { singleton: true, }, 'react-dom': { singleton: true, }, }, }); ``` And then modify the `rsbuild.config.ts` file in the root directory of `MFE1` with the following configuration: ```diff title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginReact } from '@rsbuild/plugin-react'; + import { pluginModuleFederation } from '@module-federation/rsbuild-plugin'; + import mfConfig from './module-federation.config'; export default defineConfig({ server: { port: 3001 }, plugins: [ pluginReact(), + pluginModuleFederation(mfConfig) ] }); ```
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`.