Unable to share singleton from local Angular Library
See original GitHub issueI can’t figure out how to share the same instance of an injectable service across federated Angular modules in a CLI project. I have a Git Repo that illustrates my problems.
I started from a working example, then generated a new lib (ng generate library mdmf-shared
) and exposed a single Injectable from the library’s public-api. I import this service into my shell and my microfrontend with no problem, but the microfrontend creates a new instance when it loads.
I assumed that I may just need to add the dependency to my ‘shared’ configuration in my webpack.config.ts files, but It just ends up with compilation errors.
plugins: [
new ModuleFederationPlugin({
shared: {
"@angular/core": { eager: true, singleton: true },
"@angular/common": { eager: true, singleton: true },
"@angular/router": { eager: true, singleton: true },
"mdmf-shared": { eager: true, singleton: true },
},
}),
],
if I do something like the above, I end up with an error during compile. I have tried all sorts of values using all sorts of options listed in node_modules/webpack/schemas/plugins/sharing/SharePlugin.json
, but I’m clearly out of my depth here.
Error: Module not found: Error: Can't resolve 'mdmf-shared' in '/Users/gallou/WebstormProjects/module-federation-examples/angular11-microfrontends/projects/mdmf-shell/src/app/home'
As you can tell from my examples above, I have tried making a repro project based on your angular11 example, but my repo is based on Manfred Steyers example. Both projects act the same for me once I try adding the library.
Issue Analytics
- State:
- Created 3 years ago
- Comments:9
Top GitHub Comments
I also struggled with this however I ended up getting it working. I have committed the change I made to my fork here in case that is useful for you/others
https://github.com/colinfindlay/module-federation-examples/commit/45faa1d4b637fb08eb4e3bd917e21cc8fa85164e#diff-7b53afde1320d2f674223b51cd559944ca60c6722fa481c4cc50bb57385b6c46
Incidentally what led me down this path was re-reading this part of the manual ( https://webpack.js.org/concepts/module-resolution/ )- and realising I needed to swap a module path with a relative path as the module is in my Angular workspace rather than in node_modules/package.json.
In my experience the micro-front ends often require core data or context that can be shared across apps. I think having “shell level singleton services” is an essential pattern for core data and contextual services in this micro-frontend use case - and as such it this is a useful demo. Happy to contribute this back to the examples if others agree.
Just adding some notes here in case anyone else lands on this page.
My project is an NX Monorepo using Angular CLI. I’m using (at the moment) Angular 11.0.0-next and Webpack 5, which is only available as an opt-in with ng11 at the time of writing.
If you’re on NX, your linting will complain if you import from absolute or relative library paths, so there is a disconnect between what Webpack wants, and what tslint wants. Paraphrasing the important bits of colinfindlay’s answer, you can get singletons to work across federated modules by sharing the module in your
webpack.config.ts
file. Extending his example to use the CLI, your setup could end up something like thisIt turns out I was having two problems. First, Webpack has to know how to identify the modules you are trying to share, and using the paths from your tsconfig doesn’t work. Webpack needs to know the path from root, but your apps and libs should reference the path from your tsconfig files. You can use the ‘imports’ option of a shared object to accomplish this
Here, we refer to our library by its alias path from tsconfig, but we tell Webpack where the library is actually located via the import option. This solved the ‘Module not found’ errors I was getting during compile.
My second problem was that I was attempting to share common facades depend on common data access services. I didn’t think to share the data access services because they are stateless, but this caused my MFEs to instantiate new singletons. Sharing my data access layer along with my facade layer resulted in shared singletons throughout my app.
The issue of dependencies is the most important thing here, because it’s harder to debug. There are no errors or anything – things just don’t work like you expect. You may not even realize that you have two instances of a shared service at first. So, if you run into this issue take a look at your dependencies and make sure you’re sharing everything you need. This is probably an argument for keeping minimal shared state/dependencies across your apps.
Closing this issue. Resolved.