3

I'm start using Micro Frontend with Module Federation Plugin . Now i faced with some issues on building routing between my applications. My Host application have route 3 mfe apps. Each of them have own routing inside. Navigation in Host-app is working, as inner navigation, but when i clicked again nav to hostApp/app1 when I on hostApp/app1/somePage1 it still render hostApp/app1/somePage1. What architecture you can recommend? How i can control it?Now I use react-router-dom V6 but i want to build application in way that tomorrow i can add another library like angular-router or bla-bla-bla-Router without any changes in host

export default function HostApp() {
 return (
  <BrowserRouter>
     <div>Hello, I'm the host app!</div>
     <NavLink to='/app1'> <button> app1 </button> </NavLink>
     <NavLink to='/app2'> <button> app1 </button> </NavLink>
     <NavLink to='/app3'> <button> app1 </button> </NavLink>
     <Routes>
       <Route path='/' element={
          <Suspense fallback={'Loading'}><div>home page container</div></Suspense>} />
       <Route path='app1/*' element={ 
          <Suspense fallback={'Loading'}> <MfeApp1/></Suspense>}/>
       <Route path='app2/*' element={ 
          <Suspense fallback={'Loading'}> <MfeApp2/></Suspense>}/>
       <Route path='app3/*' element={ 
          <Suspense fallback={'Loading'}> <MfeApp3/></Suspense>}/>
    </Routes>
  </BrowserRouter>
)}

MfeApp:

export default function MfeApp1() {
return (
    <BrowserRouter>
        <h1>It is a Mfe App1 </h1>
        <Routes>
            <Route index path='app1' element={<HomePageApp1 />} />
            <Route path='app1/somePAge' element={<SomePageOfMfeApp1 />} />
        </Routes>
    </>
)
}

Is it a good idea to use in both application BrowserRouter? I see a big issue here when 2 application try to control browser history. But if i leave onle one BrouserRouter in Host App i get error:"useRoutes() may be used only in the context of a component". That's also makes sense for me because inner app also need some Router to control it. I also tried to use MemoryBrowser and memory history in mfe apps and control path with callbacks like onNavigete(fromHost) and onParentNavigate(from mfe) but I failed to do it with react-router-dom V6. So any examples of working code or your advises will be so helpfull

Leon
  • 111
  • 1
  • 2
  • 5

2 Answers2

11

You don't need to use a <BrowserRouter> in the component that you export out of your remote Micro FE. You can take a look at the setup I have at https://github.com/jagadish-k/routing-module-federation Including the relevant snippets here for posterity.

In HostApp: app.jsx

export default function HostApp() {
 return (
  <BrowserRouter>
     <div>Hello, I'm the host app!</div>
     <NavLink to='/app1'> <button> app1 </button> </NavLink>
     <NavLink to='/app2'> <button> app1 </button> </NavLink>
     <NavLink to='/app3'> <button> app1 </button> </NavLink>
     <Routes>
       <Route path='/' element={
          <Suspense fallback={'Loading'}><div>home page container</div></Suspense>} />
       <Route path='/app1/*' element={ 
          <Suspense fallback={'Loading'}> <MfeApp1/></Suspense>}/>
    </Routes>
  </BrowserRouter>
)}

In MfeApp:

app.jsx

export default function MfeApp1() {
return (
    <>
        <h1>It is a Mfe App1 </h1>
        <Routes>
            <Route index element={<HomePageApp1 />} />
            <Route path='somePAge' element={<SomePageOfMfeApp1 />} />
        </Routes>
    </>
)
}

bootstrap.jsx

import React, { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";

import App from "./app";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <BrowserRouter basename="/app1">
      <App />
    </BrowserRouter>
  </StrictMode>
);

webpack.config.js

...
        exposes: {
          './MfeApp': './src/app.jsx',
        },
...

In this case, when you are independently running MfeApp, its bootstrap.jsx will be used in effect giving you access to the BrowserRouter. However when MfeApp is used in the HostApp, the Routes are rendered as a child of the Host's BrowserRouter.

jagzviruz
  • 1,453
  • 12
  • 27
0

I think there are few options how to handle that:

  1. What @jagzviruz propose , it's combination between host and remote handling the routing.

  2. https://github.com/module-federation/module-federation-examples/tree/master/react-nested-routers - the host is the responsible to update the URL.

  3. You can use BrowserHistory in both apps and to manipulate the path inside the remote app to be always with the remote app prefix ( see example here ). I think this is the easiest and understood solution, but maybe not the most effective.

OriEng
  • 1,424
  • 18
  • 34