Micro frontends let you split a frontend into smaller, independently deployable apps.
In this project, I built a very simple setup with:
- A Host App (
host-app) - A Remote App (
remote-app) - Module Federation using
@module-federation/vite
The host dynamically imports UI from the remote at runtime.
GitHub Repository
View the source code on GitHub
Why Micro Frontends?
As projects grow, a single frontend can become hard to scale across teams. Micro frontends help by:
- Allowing independent development and deployment
- Reducing coupling between teams/features
- Making incremental migration easier
For this demo, the goal was to keep things minimal and understand the core mechanics.
Project Structure
micro-frontend/
host-app/
remote-app/How Module Federation Is Configured
Remote App Configuration
In the remote app, I expose the App.tsx component:
name: "remote"filename: "remoteEntry.js"exposes: { "./remote-app": "./src/App.tsx" }reactis shared as a singleton
This generates remoteEntry.js, which the host consumes.
Host App Configuration
In the host app, I register the remote:
- Remote alias:
remote - Entry:
http://localhost:4174/remoteEntry.js - Shared
reactas singleton
Then in host-app/src/App.tsx, I load the remote with React.lazy:
const RemoteApp = lazy(() => import("remote/remote-app"));This is the key line that pulls the remote component at runtime.
Running the Apps Locally
Start the remote first:
cd remote-app
npm install
npm run devThen start the host:
cd host-app
npm install
npm run devIf everything is running, the host app renders the remote component inside Suspense.
What I Learned
- Module Federation with Vite is surprisingly straightforward for simple use cases.
- Correct remote name, expose path, and entry URL must align exactly.
- Sharing React as a singleton avoids duplicate React instances and runtime issues.
- Startup order matters in local development (remote first, then host).
Challenges Faced
- Initial alignment between expose key (
"./remote-app") and host import ("remote/remote-app"). - Ensuring both projects used compatible React versions.
- Understanding why remote entry must be reachable before host tries to load it.
Next Improvements
- Add a second remote to demonstrate feature-level composition
- Add TypeScript typings for remote modules
- Add CI/CD pipelines for independent deployment
- Add error boundaries/fallback UI when remote is unavailable
Final Thoughts
This project is a small but solid foundation for understanding micro-frontends in real-world architecture.
Even in a minimal setup, you can see the main value: independent modules, composed into one UI at runtime.
If you are exploring scalable frontend architecture, this is a great starting point.