Shared dependencies are still generated in both remote and shell app in @angular-architects/module-federation

3 min read 24-09-2024
Shared dependencies are still generated in both remote and shell app in @angular-architects/module-federation


In the world of micro-frontends, ensuring that shared dependencies are correctly managed is paramount for optimal application performance and user experience. A common issue developers encounter when using the @angular-architects/module-federation package is that shared dependencies are still being generated in both remote and shell applications. This can lead to increased bundle sizes and redundant loading of libraries, which we will address in this article.

Problem Scenario

The original problem can be summarized as follows:

"Shared dependencies are still generated in both remote and shell app in @angular-architects/module-federation."

This sentence can be simplified to: "In @angular-architects/module-federation, shared dependencies are being duplicated in both the remote and shell applications."

Understanding the Issue

In micro-frontend architecture, applications (or modules) are designed to work independently, but they often share libraries or frameworks, such as Angular. When using module federation, developers expect that shared dependencies, such as @angular/core, will only be loaded once in the shell application to minimize duplication and improve loading times.

Example of a Misconfiguration

In a typical Angular setup using module federation, you might see something like this in your webpack.config.js:

// webpack.config.js
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");

module.exports = {
  // Other configuration settings
  plugins: [
    new ModuleFederationPlugin({
      name: "shell",
      remotes: {
        remoteApp: "remoteApp@http://localhost:4201/remoteEntry.js",
      },
      shared: {
        '@angular/core': { singleton: true, eager: true },
        '@angular/common': { singleton: true, eager: true },
      },
    }),
  ],
};

If you notice that your shared dependencies are still being duplicated in both the shell and remote applications, it may be due to the configuration settings within your webpack setup.

Analysis of Configuration

Singleton vs. Eager Loading

One potential reason for duplicated dependencies could be the lack of proper configuration for shared dependencies. In the example above, the use of singleton: true ensures that the same instance of the library is used across both applications, but if the eager flag is set to true, it forces the dependency to load regardless of whether it’s already included or not.

Correct Configuration Example

To resolve this issue, you should ensure that your configuration specifies singleton and possibly remove eager:

shared: {
  '@angular/core': { singleton: true },
  '@angular/common': { singleton: true },
},

Practical Example

Imagine two Angular applications: a shell app and a remote app that both use @angular/common. If both applications are configured correctly with singleton: true, when users load the shell app, it will fetch @angular/common just once, and the remote app will utilize this single instance instead of fetching its own.

This not only optimizes performance by reducing network requests but also ensures that both apps remain synchronized with the same version of the shared library.

Additional Considerations

  1. Version Compatibility: Ensure all applications are using compatible versions of the shared dependencies. Mismatched versions can lead to runtime errors.

  2. Testing: Regularly test your setup in various environments to ensure that shared dependencies are correctly loaded. Use tools like Webpack Bundle Analyzer to visualize your bundle sizes.

  3. Documentation and Best Practices: Stay updated with the official Angular Module Federation documentation for best practices and recommendations.

Conclusion

Effectively managing shared dependencies in a micro-frontend architecture using @angular-architects/module-federation is crucial for enhancing application performance and user experience. By configuring your shared libraries correctly, you can eliminate duplication and optimize loading times.

For further reading, here are some useful resources:

By implementing these strategies and configurations, you can ensure that your Angular applications are efficient, streamlined, and free of unnecessary redundancies.