-
Notifications
You must be signed in to change notification settings - Fork 187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error: inject() must be called from an injection context #169
Comments
I covered this in my blog. Check this out: https://medium.com/p/258f331bc11e |
@deepa-7k. It happens when you load Angular more than once. In other words, you load different versions of Angular. Checkout this config from https://github.com/vugar005/youtube-webapp-lerna/blob/master/likes-app/src/bootstrap.ts |
As @vugar005 says. You are very likely using different (perhaps only slightly different) versions of Angular (due to package.json or package-lock.json) |
Thank you for the response. We will check the config which you have shared. Also just wanted to know, if this inject error occurs due to different versions of Angular packages, will it occur every time we try to load the MFE? What we face is something that occurs very randomly and mostly not reproducible with manual testing. |
hello i'm having the same issue using nx repo with angular/core 12.2.16 core.js:6498 ERROR Error: Uncaught (in promise): Error: inject() must be called from an injection context |
@deepa-7k yes it would happen whenever a new Angular app is going to be bootstrapped. |
If I understand correctly: if we want to use some shared angular lib that calls inject() funcion there is NO WAY we can run multiple different versions of Angular (like explained in this article https://www.angulararchitects.io/aktuelles/multi-framework-and-version-micro-frontends-with-module-federation-your-4-steps-guide/). In that case all micro frontend apps must be build on the same Angual version? Is that right @vugar005, @manfredsteyer? My example: this error UPDATE: UPDATE 2: I have tested by using this configuation in wepack.config.js under ModuleFederationPlugin: Config for host app (running angular 13):
Config for remote app (running angular 12):
With this configuration, host app downloads ngx-datatable module, and also remote app downloads it and use it's own instance. Works brilliant. BTW: I also tried to use |
Hi jure123 ... can you maybe explain a bit more of steps how you solved multiple angular (core) versions at the same time? My shell is running for example with A16 and my MFEs are under A15. So I am getting thus mentioned error above |
@ArgV04, my example mentioned two comments above solved my problem. I have posted config for host/shell app that is running Angular 13 and useing ngx-datatable 13; and config for remote apps that are running on Angular 12 and using ngx-datatable 12. You shall probably use similar config, but instead of ngx-datatable (that was causing the issue in my project) you should define library or more libs that are causing inject() error (I think you can find it in error stack trace, but I forgot). If you can't find the libs you can try to add to both configs (or only remote config maybe) all libs that each project is using. Make sure shareKey has different value in shell and remote config. If you put in shell config all libs that shell is using, and in remote config all libs remote is using, and define different shareKey values, then I believe it should work, because remote federation will make sure that each project only uses their own libs. I haven't tested this in later Angular versions, I hope they don't cause some additional issues. |
Yeah I tried your config ... and here is an error log output for example :) ... so I think shareKey is maybe working somehow but Angular uses some globalState dependencies, liked mentioned here. So just wondering how this was working on your side, when trying to initialize multiple angular/core, zone dependencies trying to setup multiple global states at runtime ... |
From your error stack trace it seems there is issue with RouterModule. Did you try to use "solution 3" mentioned here (the article you already posted).
I guess in your case shell config should have requiredVersion 16, remote should have 15. Apparently in my case I haven't had this issue because I didn't use conficting providers from @angular/router, or maybe there was not conflict between Angular 12 and 13 that I used. Our team found these kind of version conflicts too risky (and unpredictable) for the serious long term use of module federation for larger projects (unless we could agree that we always updated shell and all remotes to the same Angular version, which is not possible for larger long term projects). |
I am currently also evaluating using module federation for our products. A simple test trying to use an mfe with angular 16 in a shell with angular 17 fails with this mentioned error. Is this simply not possible? Our intention is to be able to update our products gradually to new versions which would not be possible if we cannot get different versions to work with each other. @jure123 |
@digaus, as I mentioned two comments above, I think that possiblilty of different Angular versions conflict is too unpredictable and too risky to use MFE concept in large-scale long term projects. The risk is not only with differnt versions of Angular core libraries, but also with different versions of other 3rd party UI libraries that may cause incompatible JS or even CSS. In our large project we have decided to develop different custom approach that we called "Multi-SPA", where different MFE apps are built separately (like standard SPA), but not with header, footer and navigation menu, only their content part. Then we built a special "Layout app" that is loaded in each SPA (as a single JS file), which renders header/footer/menu around the SPA content. Each SPA is deployed in a separate folder (/mfe1, /mfe2, ...). When user jumps from one MFE to another the browser it's similar like your would jump from one web site to another: the first SPA is destroyed from browser DOM completely (HTML/JS/CSS), and the new MFE app is rendered from stratch. But both load the same Layout script that renders the same Layout, so the user experiences seprate apps to look and feel as one portal. The advantage of our approach is absolutely no risk of conflicts between MFE apps (we tested with Angular 14,15,16, Angular Universal, React, Vue), and each SPA can use it's own 3rd party libs without in any versions. The down side is that switching MFE apps takes a performance hit, as all JS bundles have to be loaded and parsed from stracth. But in practice, only the first load takes a bit more time, after that browser loads JS/CSS from disk or memory cache and it works quite fast (although not as smootly as in the classic MFE shell-remote concept). We use this approach for CRM portal which is assembled with many separate SPAs that load the same "Layout script", and we are very pleased with the solution. However it took quite some investigations and custom solutions how to communicate between SPA and our Layout app (who controls user authentication, how navigation menu causes route change when jumping pages inside one SPA or jumping to different SPA, etc.). No simple MFE solution in the world yet :) |
We are getting this error also when using native-federation with webcomponents. While we thought this is the most robust / independent variant, the following situation leads to the error:
In this case, both versions of angular will be loaded (as expected). Also only a single version of primeng will be loaded (shared, since the version is the same). But now primeng tries to call inject, in both shell and mfe. One of those will fail, since they target different versions of angular and different injection context. To solve this it would be helpful to be able to couple the sharing of angular and a lib like primeng: Share the lib version if and only if the angular version is also shared. Use a separate bundle of the lib, even if the version is the same, if the angular version is not shared. While in module federation this could be solved with a share key, if I understand the above comment correctly, I do not see any option for this in native federation. |
We get the below error when trying to call a microfrontend. The issue occurs only at times and fails to load the MFE
main.52b1fee5a0c17f23f7ca.js:1 ERROR Error: Uncaught (in promise): Error: inject() must be called from an injection context
Error: inject() must be called from an injection context
at _r (remoteEntry.js:471:169)
at wr (remoteEntry.js:471:342)
at Module.Ec (remoteEntry.js:902:157)
at po.e.ɵfac [as factory] (934.c221672f75e97217c5b8.js:1:7157)
at _t (main.52b1fee5a0c17f23f7ca.js:1:142547)
at main.52b1fee5a0c17f23f7ca.js:1:192374
at Wb (main.52b1fee5a0c17f23f7ca.js:1:192445)
at gh.create (main.52b1fee5a0c17f23f7ca.js:1:276234)
at py.createComponent (main.52b1fee5a0c17f23f7ca.js:1:253831)
at h. (405.627f7ca446d7f03d3443.js:1:6554)
at rn (polyfills.6a402a4b8539d95a42ad.js:1:1740824)
at polyfills.6a402a4b8539d95a42ad.js:1:1739784
at R (405.627f7ca446d7f03d3443.js:1:95547)
at ln.invoke (polyfills.6a402a4b8539d95a42ad.js:1:1730740)
at Object.onInvoke (main.52b1fee5a0c17f23f7ca.js:1:304055)
at ln.invoke (polyfills.6a402a4b8539d95a42ad.js:1:1730674)
at Ln.run (polyfills.6a402a4b8539d95a42ad.js:1:1725789)
at polyfills.6a402a4b8539d95a42ad.js:1:1741725
at ln.invokeTask (polyfills.6a402a4b8539d95a42ad.js:1:1731392)
at Object.onInvokeTask (main.52b1fee5a0c17f23f7ca.js:1:303871)
Tv @ main.52b1fee5a0c17f23f7ca.js:1
We tried giving the exact version of Angular packages required in our webpack configs both in shell and child applications and also tried using singleton but none of them has solved the issue. Please advise on what can be done or what could be the issue here
The text was updated successfully, but these errors were encountered: