|
| 1 | +🔹 Microfrontend Routing Requirements (Explained) |
| 2 | + |
| 3 | +1. Both the Container + Individual SubApps need routing features |
| 4 | + |
| 5 | +- The container app handles top-level navigation (e.g.,` /auth`, `/dashboard`). |
| 6 | + |
| 7 | +- Each sub-app may also have its own routes (`/auth/login`, `/auth/signup`). |
| 8 | + |
| 9 | +- Both must coexist without clashing. |
| 10 | + |
| 11 | +2. Sub-apps might need to add in new pages/routes all the time |
| 12 | + |
| 13 | +- Teams should be able to add or update routes inside their own microfrontend without modifying the container. |
| 14 | + |
| 15 | +- Example: Marketing team adds `/pricing` → should work without container changes. |
| 16 | + |
| 17 | +3. We might need to show two or more microfrontends at the same time |
| 18 | + |
| 19 | +- Sometimes, the container needs to render multiple MFEs together (e.g., Dashboard showing `Analytics + Notifications`). |
| 20 | + |
| 21 | +- Routing should allow parallel rendering. |
| 22 | + |
| 23 | +4. We want to use off-the-shelf routing solutions |
| 24 | + |
| 25 | +- Instead of building custom routing logic, we rely on libraries like React Router, Angular Router, Vue Router. |
| 26 | + |
| 27 | +- Each MFE can use the same routing library to simplify integration. |
| 28 | + |
| 29 | +5. We need navigation features for sub-apps in both hosted mode and in isolation |
| 30 | + |
| 31 | +- Sub-app must work standalone (`npm start`) with routing. |
| 32 | + |
| 33 | +- Sub-app must also work inside the container (`npm run serve`) without breaking. |
| 34 | + |
| 35 | +6. If different apps need to communicate about routing, it should be generic |
| 36 | + |
| 37 | +- Avoid hardcoding "container tells sub-app X". |
| 38 | + |
| 39 | +- Use events or history API so MFEs remain independent. |
| 40 | + |
| 41 | +- Example: If user navigates in container → sub-apps should respond via shared history object. |
| 42 | + |
| 43 | +Routing in MFE: |
| 44 | + |
| 45 | +```ascii |
| 46 | + +------------------+ |
| 47 | + | Container | |
| 48 | + | (Global Routes) | |
| 49 | + +------------------+ |
| 50 | + / | \ |
| 51 | + / | \ |
| 52 | + v v v |
| 53 | + +----------------+ +----------------+ +----------------+ |
| 54 | + | SubApp A | | SubApp B | | SubApp C | |
| 55 | + | (/auth/*) | | (/dashboard/*) | | (/marketing/*) | |
| 56 | + +----------------+ +----------------+ +----------------+ |
| 57 | +
|
| 58 | +[Features Needed] |
| 59 | +1. Container + SubApps both define routes |
| 60 | +2. SubApps can add new routes freely |
| 61 | +3. Multiple SubApps can render at same time |
| 62 | +4. Use off-the-shelf routers (React Router, etc.) |
| 63 | +5. SubApps work standalone & inside container |
| 64 | +6. Routing communication must be generic |
| 65 | +``` |
| 66 | + |
| 67 | +🧩 Problem Setup |
| 68 | + |
| 69 | +- Container App |
| 70 | + |
| 71 | + - Has a header with a logo → supposed to redirect to `/`. |
| 72 | + |
| 73 | + - No routing logic in container (just renders sub-apps). |
| 74 | + |
| 75 | +- Marketing App |
| 76 | + |
| 77 | + - Has its own routes: |
| 78 | + |
| 79 | + - `/` → Landing Page |
| 80 | + |
| 81 | + - `/pricing` → Pricing Page |
| 82 | + |
| 83 | +- What happens now? |
| 84 | + |
| 85 | + - You navigate to `/pricing` (shows Pricing page ✅). |
| 86 | + |
| 87 | + - You click Logo in Container → container changes URL to `/`. |
| 88 | + |
| 89 | + - But UI still shows Pricing (❌), because Marketing App’s router didn’t notice container’s navigation. |
| 90 | + |
| 91 | +Why this happens? |
| 92 | + |
| 93 | +Since container has no routing logic, it doesn’t mount/unmount MFEs based on route. |
| 94 | + |
| 95 | +- Marketing is always mounted. |
| 96 | + |
| 97 | +- React Router inside Marketing listens to its own history instance. |
| 98 | + |
| 99 | +- But when Container changes URL → Marketing’s router doesn’t get updated (they are disconnected). |
| 100 | + |
| 101 | +Solution |
| 102 | + |
| 103 | +Yes – you do need routing logic at the container level (at least minimal). |
| 104 | + |
| 105 | +Two Approaches: |
| 106 | + |
| 107 | +1. Container controls which sub-app mounts (Recommended) |
| 108 | + |
| 109 | +- Container uses its own router (React Router, Vue Router, etc.). |
| 110 | + |
| 111 | +- Example: |
| 112 | + |
| 113 | + - `/` → render Marketing (Landing) |
| 114 | + |
| 115 | + - `/pricing` → render Marketing (Pricing) |
| 116 | + |
| 117 | + - `/auth/*` → render Auth app |
| 118 | + |
| 119 | +This way → when logo navigates to `/`, container re-renders Marketing at root route → React Router inside Marketing will naturally show Landing. |
| 120 | + |
| 121 | +2. Share history between Container + SubApp (Advanced) |
| 122 | + |
| 123 | +- Instead of container routing, pass down a shared `history` object to sub-apps. |
| 124 | + |
| 125 | +- Container navigation (`/`) triggers same history object → Marketing router updates. |
| 126 | + |
| 127 | +- This requires wiring React Router in both places to the same history. |
| 128 | + |
| 129 | +Rule of Thumb |
| 130 | + |
| 131 | +- If container should control which microfrontend shows up → container must have routing logic. |
| 132 | + |
| 133 | +- If container is “dumb shell” and only loads one sub-app at a time → share history so both stay in sync. |
| 134 | + |
| 135 | +🔧 Fix for Your Case |
| 136 | + |
| 137 | +Since you said container has no routing but has a header with logo: |
| 138 | + |
| 139 | +- Best Fix → Add minimal routing in container: |
| 140 | + |
| 141 | +```tsx |
| 142 | +// ContainerApp.tsx |
| 143 | +import { BrowserRouter, Route, Routes } from "react-router-dom"; |
| 144 | +import MarketingApp from "./MarketingApp"; |
| 145 | + |
| 146 | +export default function ContainerApp() { |
| 147 | + return ( |
| 148 | + <BrowserRouter> |
| 149 | + <Header /> {/* Logo inside this navigates to "/" */} |
| 150 | + <Routes> |
| 151 | + <Route path="/*" element={<MarketingApp />} /> |
| 152 | + </Routes> |
| 153 | + </BrowserRouter> |
| 154 | + ); |
| 155 | +} |
| 156 | +``` |
| 157 | + |
| 158 | +Note: - in microfrontends we typically share either BrowserHistory or MemoryHistory, depending on how we want the container and child apps to sync. |
| 159 | + |
| 160 | +ASCII Diagram for this particular project router setup: |
| 161 | + |
| 162 | +```sql |
| 163 | + +---------------------------+ |
| 164 | + | CONTAINER | |
| 165 | + | React Router (Browser) | |
| 166 | + | Controls real URL bar | |
| 167 | + +-------------+-------------+ |
| 168 | + | |
| 169 | + ----------------------------------------------- |
| 170 | + | | |
| 171 | ++-------------------------+ +-------------------------+ |
| 172 | +| MARKETING | | AUTH | |
| 173 | +| React Router (Memory) | | React Router (Memory) | |
| 174 | +| Local navigation only | | Local navigation only | |
| 175 | +| Not changing URL bar | | Not changing URL bar | |
| 176 | ++-------------------------+ +-------------------------+ |
| 177 | + |
| 178 | +``` |
| 179 | + |
| 180 | +Why This Router Setup? |
| 181 | + |
| 182 | +In a microfrontend (MFE) system: |
| 183 | + |
| 184 | +- Container App is responsible for the overall application and controls the real browser URL. That’s why it uses Browser History (so the URL is synced, bookmarkable, reloadable). |
| 185 | + |
| 186 | +- Sub-apps (Marketing, Auth, etc.) are mounted inside the container. If they also tried to use `BrowserHistory`, multiple apps could fight over the URL at the same time. |
| 187 | + |
| 188 | +- To prevent this conflict, sub-apps use Memory History. |
| 189 | + |
| 190 | + - MemoryHistory keeps routing changes local to the sub-app. |
| 191 | + |
| 192 | + - When the container needs to know about navigation, the sub-app can “notify” the container. |
| 193 | + |
| 194 | + - The container then decides if/when to update the actual browser history. |
| 195 | + |
| 196 | +This way, we get a clean separation: |
| 197 | + |
| 198 | +- Container = controls the real URL. |
| 199 | + |
| 200 | +- Sub-apps = handle their own routing internally without breaking others. |
| 201 | + |
| 202 | +**Benefits of this Approach** |
| 203 | + |
| 204 | +- Avoids conflicts → Only one app (the container) controls the real URL. |
| 205 | + |
| 206 | +- Isolation → Sub-apps can add/remove routes anytime without breaking container or other MFEs. |
| 207 | + |
| 208 | +- Flexibility → Container can decide when to sync sub-app navigation with the real URL. |
| 209 | + |
| 210 | +- Scalability → More MFEs can be added without changing routing strategy. |
0 commit comments