Reputation: 16986
I have an angular project structured like so:
Site1
Site2
I know this isn't ideal, but it's how it is.
The package.json
files are exactly the same apart from the names of the application.
The project was started on Angular 8 and has always upgraded well, but going from 11 -> 12 I'm having issues:
Site1 builds fine and runs nicely. Site2 builds fine, but errors immediately on running with
Error: inject() must be called from an injection context at injectInjectorOnly (core:4745) at Module.ɵɵinject (core:4755) at Object.RouterModule_Factory [as factory] (router:5999) at R3Injector.hydrate (core.js:11438) at R3Injector.get (core.js:11257) at core.js:11295 at Set.forEach () at R3Injector._resolveInjectorDefTypes (core.js:11295) at new NgModuleRef$1 (core.js:25325) at NgModuleFactory$1.create (core.js:25379)
As Site1 works fine, I assume it must be something in calling that SharedModule?
I've tried adding "preserveSymlinks": true,
to projects.$name.architect.build.options, but that doesn't work. I'm not using npm link
as the other module isn't a library (I know it should have been set up that way, but it isn't).
I've spent at least 2 days trying to get this to work (obviously checking posts such as this and this, but the answers there dont seem to work.
Does anyone know how to fix this, or at least how to debug it please?
Upvotes: 6
Views: 12546
Reputation: 21
The two most common tips for this problem are:
For me in Angular 17, I had to delete
all paths from tsconfig.json but leave
"preserveSymlinks": true
This led me to the solution: https://github.com/angular/angular/issues/35586#issuecomment-2137243609
Upvotes: 0
Reputation: 3315
I know this is a relatively old question but yesterday I had a similar issue and my workspace was already correctly configured as the example that was posted in the answer, on top of that it took a lot of googling to find another solution so I thought it would be best to share it somewhere with more visibility.
My issue was that if I injected a service from my local library without other dependencies it worked fine but if I injected a service that had to inject other dependencies into itself I had the same error showed in the question. The cause was exactly the same (2 different instances of angular) but what solved it for me was this
https://github.com/angular/angular/issues/25813#issuecomment-584866010
For me,
"@angular/*": [ "./node_modules/@angular/*" ]
(one dot, not two in the path) was what I needed, in addition to my own other mappings for my libraries. This only applies when using TypeScript path mapping instead of linking to the libraries, as documented here. Also, I put it in the tsconfig.json, not tsconfig.app.json. Either worked.So the paths portion of my tsconfig.json file in my main Angular app is:
{ ..., "compilerOptions": { ..., "paths": { "@angular/*": ["./node_modules/@angular/*"], "mylib/*": ["../../location/of/my/lib/src/*"] } }, ... }
I added "@angular/*": [ "./node_modules/@angular/*" ]
to my tsconfig.json and it worked.
Despite the fact the github issue was closed saying it was solved with the release of Ivy I had this issue with angular 12 while using ivy
Upvotes: 7
Reputation: 16986
For the benefit of searchers, following not getting a response here, I asked this to Angular themselves.
Here are the answers provided.
You have two distinct workspace trees that import from each other. That is bound to suffer from duplicate @angular/core versions which confuses the runtime, resulting in the rather obscure runtime error you're seeing. You can workaround this using paths mappings, as explained in the library guide here (which also applies to your situation without libs). Not sure why it worked in earlier versions, it has always been prone to these kinds of issues.
and
The cause is that the two separate workspaces both have their own @angular/core packages, and both end up in the bundled application. The Angular runtime keeps its state in top-level module variables that are private to that module, but having two occurrences of that module (from both instances of @angular/core) you run into situations where state is only initialized correctly in one instance, not the other. In this case the injection context is only available in the "primary" runtime, but the parts of the app that were bundled from the "secondary" library parts will depend on the "secondary" runtime state.
So basically, the structure is bad. It should have been done as a proper library project in the first place.
I've made a demo of how it should have been done here.
Upvotes: 7