Micro-Frontends in React: When Monoliths Become a Nightmare
I still remember the day our main Webpack build crossed the 15-minute mark. Developers were literally taking coffee breaks just to see a CSS change compile. The "agile" team had ground to a halt because everyone was stepping on each other's toes in the exact same React repository.
The Tipping Point
We realized that scaling the backend with microservices is common sense, but frontend architecture is usually left behind. We had 5 different product teams trying to deploy independently, but they were bound by a single package.json and a fragile deployment pipeline. If Team A pushed a bad dependency update, Team B's checkout page went down.
Enter Webpack Module Federation
We evaluated iframes (terrible UX), build-time composition (still requires a massive monolithic build), and finally landed on Webpack Module Federation. This allowed us to dynamically load code at runtime.
Suddenly, the "Checkout" team could deploy their React components to their own CDN bucket, and the "Catalog" team's shell application would seamlessly pull in the updated UI on the next page refresh. No monolithic build required.
The Hidden Traps
It wasn't all sunshine. The biggest pain point we encountered was shared state. How does the Cart micro-frontend talk to the Navigation micro-frontend? We initially over-engineered a complex event bus. Big mistake. We eventually stripped it back to relying heavily on URL state and standard React Context at the shell level. Keep the micro-frontends dumb; let the shell orchestrate.
If your team is under 10 developers, don't do this. A monolith is fine. But if you have multiple autonomous squads, micro-frontends might just save your sanity.