Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular cyclic dependency when enabling ivy

After enabling ivy in my angular project, everything compiles but when starting the app in the browser I get the following error during app bootstrap:

Error: Cannot instantiate cyclic dependency! ApplicationRef
    at throwCyclicDependencyError (core.js:5208)
    at R3Injector.push../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.R3Injector.hydrate (core.js:11763)
    at R3Injector.push../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.R3Injector.get (core.js:11590)
    at injectInjectorOnly (core.js:648)
    at ɵɵinject (core.js:653)
    at injectArgs (core.js:730)
    at Object.factory (core.js:11858)
    at R3Injector.push../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.R3Injector.hydrate (core.js:11767)
    at R3Injector.push../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.R3Injector.get (core.js:11590)
    at injectInjectorOnly (core.js:648)

I'm struggling to find out where the cyclic dependency is and why it works fine when not using ivy. I tried using madge (madge --circular --extensions ts ./) but no circular dependency's where found.

Edit: I've manually gone though all my services and verified that there is no cyclic dependency between them

like image 835
that_guy Avatar asked Oct 11 '19 15:10

that_guy


People also ask

How would you fix a cyclic dependency?

A cyclic dependency is an indication of a design or modeling problem in your software. Although you can construct your object graph by using property injection, you will ignore the root cause and add another problem: property injection causes Temporal Coupling. Instead, the solution is to look at the design closely.

How do I get around circular dependency?

To reduce or eliminate circular dependencies, architects must implement loose component coupling and isolate failures. One approach is to use abstraction to break the dependency chain. To do this, you introduce an abstracted service interface that delivers underlying functionality without direct component coupling.

What is cyclic dependency in angular?

A cyclic dependency exists when a dependency of a service directly or indirectly depends on the service itself. For example, if UserService depends on EmployeeService , which also depends on UserService . Angular will have to instantiate EmployeeService to create UserService , which depends on UserService , itself.

How is cyclic dependency detected?

Analyze cyclic dependenciesFrom the main menu, select Code | Analyze Code | Cyclic Dependencies. In the Specify Cyclic Dependency Analysis Scope dialog, select the scope of files that you want to analyze. Select the Include test sources option if you want to analyze your test code together with the production code.


2 Answers

Turns out that in my app.module providers I had a class with {provideIn: 'root'} in the @Injectable(), removing that fixed it.

providers: [
    { provide: ErrorHandler, useClass: AppErrorHandler }
]

Before

@Injectable({ providedIn: 'root' })
export class AppErrorHandler implements ErrorHandler {

After

@Injectable()
export class AppErrorHandler implements ErrorHandler {

I don't know why this wasn't a problem before ivy, even with AoT

like image 143
that_guy Avatar answered Oct 22 '22 18:10

that_guy


You must be injecting the Router somewhere in any of your services which uses @Injectable. So you got two options:

Solution 1

Remove the dependency of router: Router from your service constructor.

Solution 2

Upgrade to a minimum Angular 9.0.3 which fixes this issue of cyclic dependency.

(Got fixed in this MR https://github.com/angular/angular/pull/35642)

like image 1
Shashank Agrawal Avatar answered Oct 22 '22 18:10

Shashank Agrawal