DEV Community

Taha Majlesi Pour
Taha Majlesi Pour

Posted on

๐Ÿ› ๏ธ Refactoring Legacy React Apps: The Micro-Frontend Path

Our React app started like a puppy ๐Ÿถ. Cute, small, easy.
Five years later, it was a Great Dane chewing through our furniture ๐Ÿช‘.

  • Every feature slowed us down.

  • Every release felt risky.

  • The โ€œquick fixesโ€ piled up into tech debt.

We needed a way to break it apart without hitting โ€œrewrite from scratch.โ€
Micro-frontends became our path.

Hereโ€™s how we split a monolith React app into micro-frontends, the pitfalls we hit, and the lessons weโ€™d pass on.


๐Ÿ“– A Quick Story

When we pitched micro-frontends to leadership, the promise sounded perfect โœจ: independent teams, faster deployments, cleaner boundaries.

  • Reality check:

  • Routing chaos,

  • Dependency drift,

  • UI looking like a patchwork quilt ๐ŸŽจ.

  • And laptops screaming during local dev.

Still, breaking apart the monolith taught us valuable lessons worth sharing.


๐Ÿ—‚๏ธ Step 1: Define the Boundaries

You canโ€™t just slice at random. We first mapped the appโ€™s domains: auth, dashboard, checkout, settings. These became our candidate micro-frontends.

Tip: Slice by business capability , not by components. A โ€œheader micro-frontendโ€ is a recipe for pain.


๐Ÿ›ฃ๏ธ Step 2: Routing the Split

The monolithโ€™s react-router setup assumed one app. Micro-frontends demand a single โ€œshellโ€ that delegates routes.

Example:

<BrowserRouter>
  <Routes>
    <Route path="/dashboard/*" element={<DashboardApp />} />
    <Route path="/checkout/*" element={<CheckoutApp />} />
  </Routes>
</BrowserRouter>
Enter fullscreen mode Exit fullscreen mode

Pitfall : Overlapping routes caused chaos until we defined clear ownership of paths.


๐Ÿ”— Step 3: Handling Shared State

Our monolith had one Redux store. Duplicating that across apps = trap.
We isolated state per domain, then created a shared session store for auth.

Example:

import { createStore } from 'zustand';

export const useSession = createStore((set) => ({
  user: null,
  setUser: (user) => set({ user })
}));
Enter fullscreen mode Exit fullscreen mode

Lesson: Share as little state as possible. Every extra slice ties teams back together.


โš™๏ธ Step 4: Splitting the Build

We used Webpack Module Federation to load micro-frontends at runtime. Each team owned its build, but the shell wired them together.

Example:

new ModuleFederationPlugin({
  name: 'checkout',
  filename: 'remoteEntry.js',
  exposes: {
    './CheckoutApp': './src/App',
  },
});
Enter fullscreen mode Exit fullscreen mode

Pitfall: Version drift โš ๏ธ. If one app shipped React 18 and another React 17 โ†’ runtime errors.


๐ŸŽจ Step 5: Tackling UI Consistency

Once split, each team styled differently. The UI looked like a collage ๐Ÿ–ผ๏ธ.

Fix: We built a shared design system package. Components were pulled live, not copied.


๐Ÿ’ป Step 6: Local Development Without Tears

At first, running the shell + every micro-frontend crushed laptops ๐Ÿ–ฅ๏ธ๐Ÿ”ฅ. Coffee cooled while builds spun.

Solution: Built mocks and stubs. Local dev usually meant one micro-frontend + stubbed neighbors.


๐Ÿ—บ๏ธ The Roadmap Weโ€™d Recommend

  • Map domains first โ€” avoid atom-sized micro-frontends.

  • Centralize routing โ€” clear ownership of URL paths.

  • Keep shared state minimal โ€” only what must be global.

  • Align dependencies early โ€” React versions, styling, libraries.

  • Adopt a design system early โ€” stops UI drift.

  • Stub for local dev โ€” save your laptop (and sanity).


๐Ÿ“Œ Practical Takeaways

  • Micro-frontends are surgery ๐Ÿฉบ, not a silver bullet.

  • Split by business capability , not UI pieces.

  • Align on dependencies + design systems early.

  • Test local dev workflows before scaling to teams.


๐ŸŽ Something Extra (Resources)


๐Ÿ™Œ More Like This? Letโ€™s Connect!

๐Ÿ“ฒ Follow me for more dev tips, tools, and trends!

๐Ÿ”‘ Interface Insider (exclusive): Join the community โ€“ share, learn, and collaborate with other members!

Check out my latest dev articles and tutorials โ€” updated weekly!

Letโ€™s keep building cool stuff ๐Ÿš€

Top comments (3)

Collapse
 
hashbyt profile image
Hashbyt

A very practical guide to taming a React monolith. Your emphasis on splitting by business capability, not components, is the crucial takeaway many teams miss.

Collapse
 
tahamjp profile image
Taha Majlesi Pour

Thanks! Yeah, that distinction made a huge difference for us โ€” organizing by capability keeps things way saner over time.

Collapse
 
tahamjp profile image
Taha Majlesi Pour

๐Ÿ™Œ Thanks for reading! Follow me for more front-end tips ๐Ÿ’ก