πŸš€ Building a Simple Micro Frontend with Vite + React + Module Federation

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" }
  • react is 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 react as 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 dev

Then start the host:

cd host-app
npm install
npm run dev

If everything is running, the host app renders the remote component inside Suspense.

What I Learned

  1. Module Federation with Vite is surprisingly straightforward for simple use cases.
  2. Correct remote name, expose path, and entry URL must align exactly.
  3. Sharing React as a singleton avoids duplicate React instances and runtime issues.
  4. 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.

Read more blogs
Β© Prathamesh