Configuring Host and Remote React Apps
Set up exposes, remotes, and shared dependencies in webpack.config.js for a host shell and two React remotes.
Configuring Host and Remote React Apps is a free React Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Remote webpack.config.js: ModuleFederationPlugin
The remote application adds ModuleFederationPlugin to its webpack config with three key properties: name (unique identifier, e.g., "buttonApp"), filename ("remoteEntry.js" — the manifest output), and exposes (a map from public name to source file path).
Exposing Components from the Remote
The exposes configuration maps a public module path to a local file: { './Button': './src/Button' }. This means the host can import 'buttonApp/Button' and receive the component from ./src/Button.tsx. You can expose multiple components, utilities, or even entire pages.
Shared Configuration on the Remote
The shared property tells Module Federation which modules should be shared across host and remote rather than duplicated. For React: shared: { react: { singleton: true, requiredVersion: deps.react }, 'react-dom': { singleton: true } }. singleton:true prevents multiple instances from loading simultaneously.
Host webpack.config.js: Referencing Remotes
The host application's ModuleFederationPlugin config includes a remotes property: { buttonApp: 'buttonApp@http://localhost:3001/remoteEntry.js' }. The key is the import namespace, the value is the remote's name and URL combined with @ — telling Webpack where to fetch the remote at runtime.
Consuming the Remote in React
In the host's React code, import the remote component with dynamic import: const Button = React.lazy(() => import('buttonApp/Button')). The import path matches the remote's namespace and the exposed module name. React.lazy makes the import code-split and asynchronously loaded.
Wrapping with Suspense
Since remote modules are loaded asynchronously, always wrap the lazy-imported remote component in a Suspense boundary: Suspense fallback=Loading... /. The fallback renders while Module Federation fetches remoteEntry.js and the component chunk from the remote URL.
Why Singletons Are Critical
React's hooks (useState, useContext, useEffect) depend on a single internal React instance to track component state. If both the host and remote load their own copy of React, hooks will throw "invalid hook call" errors. singleton:true forces them to share one React instance, resolving this class of bugs entirely.
Version Conflict Resolution
When host uses react@18.2.0 and remote uses react@18.3.0, Module Federation's shared scope negotiates which version to use. With singleton:true and requiredVersion, it typically uses the higher version if compatible. Setting requiredVersion: '>=18.0.0' instead of a pinned version allows flexible version ranges.
TypeScript: Module Declarations
TypeScript doesn't know about remote modules at compile time, so imports like import('buttonApp/Button') will throw type errors without declarations. Use @module-federation/typescript or manually create .d.ts files that declare the module types, giving you type safety for remote component props.
Testing the Setup Locally
Run both apps simultaneously: the remote on port 3001 and the host on port 3000. Open the host — its Module Federation runtime will fetch http://localhost:3001/remoteEntry.js, discover the Button module, download its chunk, and render it inside the host app as if it were a local component.
Production URL Configuration
In production, replace localhost:3001 with the deployed remote's URL. A common pattern is to use an environment variable for the remote URL so CI/CD can inject the correct URL per environment: buttonApp: 'buttonApp@' + process.env.BUTTON_REMOTE_URL + '/remoteEntry.js'.
Singleton Shared Modules
Why must React be configured as a singleton in Module Federation's shared configuration?
Lesson Recap
Configuring Module Federation requires ModuleFederationPlugin on both remote (with name, filename, exposes) and host (with remotes). Consume remote components via React.lazy + dynamic import wrapped in Suspense. React and React DOM must be shared singletons to prevent multiple-instance hook errors. TypeScript declarations and environment-variable remote URLs complete a production-ready setup.
Frequently asked questions
Is the “Configuring Host and Remote React Apps” lesson free?
Yes — the full text of “Configuring Host and Remote React Apps” is free to read here on the web, and the React Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Academy course, upgrade to CoddyKit PRO.
What will I learn in “Configuring Host and Remote React Apps”?
Set up exposes, remotes, and shared dependencies in webpack.config.js for a host shell and two React remotes. You practise React Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start React Academy?
No prior experience is required. React Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Configuring Host and Remote React Apps” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this React Academy lesson?
Yes. Every React Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Module Federation: Dynamic Runtime Imports
- Configuring Host and Remote React Apps
- Sharing State and Routing Between Remotes
- Versioning, Deployment, and Orchestration