Search code examples
angularroutermicro-frontendangular-native-federation

Prevent Angular router from reloading a Micro Frontend component


I'm using the Native Federation architecture to load a Micro Frontend into a Shell. The Micro Frontend contains an iFrame which loads a legacy AngularJS application. The AngularJS application uses an internal mechanism to switch tabs based on IDs.

The idea

The idea is to put buttons in the shell, use the modern routing mechanism of the Shell to show routes in the browser (e.g. for bookmarking etc). When a button in the Shell is clicked, instead of routing to a different Angular Component, it shall route to the same Component. The route will then be translated to one of the corresponding IDs (mentioned above) and sent to the AngularJS application to switch its tabs.

The problem

The problem is, that every time a button in the Shell is clicked and the routing is performed, the Micro Frontend (and thus the iFrame) is reloaded.

What I've tried

I already implemented a custom RouteReuseStrategy class, but this seems to work only with regular Angular components (unless I did something wrong) and obviously not with components loaded via loadComponent() The way I'm loading the Micro Frontend in the route is as follows:

  {
    path: 'my-legacy-app',
    pathMatch: 'full',
    loadComponent: () =>
      loadRemoteModule({
        remoteName: 'my-legacy-app',
        exposedModule: './Component'
      }).then(module => module.MyLegacyAppComponent)
  }

I also found this post Making IFrame persistant with route Reuse and angular which looks like a duplicate, but it is not, because it is not related to Micro Frontends. The interesting thing is, that the user seems to have the same problem even without Micro Frontends. That would indicate that the problem is not specific to Micro Frontends.

Question

Is there a way to prevent Angular's router from reloading Micro Frontends when routing to the same Micro Frontend component, while showing the selected route in the browser?


Solution

  • Finally I found the solution. Indeed the way to go is RouteReuseStrategy. When I tried it first, I used the content for the shouldReuseRoute() function from a post on the internet. It looked like this:

    shouldReuseRoute (future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
      return future.routeConfig === curr.routeConfig;
    }
    

    The problem is, that for unknown reason the future and curr parameters are undefined when the method is called. I haven't found out why so far. Thus shouldReuseRoute() never returned true and in consequence routes were never re-used. Using return true now always re-uses the routes. Which means when navigating to a different route, the path in the URL is changing, but the component is not changed/reloaded. That's exactly what I need.

    In general the behavior is hard to understand because a lot of the methods of RouteReuseStrategy are called multiple times. I don't understand why.