Skip to content
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

feat(@angular/cli): add circular dependency detection #6813

Merged
merged 1 commit into from
Jun 27, 2017

Conversation

filipesilva
Copy link
Contributor

@filipesilva filipesilva commented Jun 27, 2017

Circular dependencies, like app.module.ts importing app.component.ts which in turn imports app.module.ts, now display a warning during builds:

kamik@T460p MINGW64 /d/sandbox/master-project (master)
$ ng build
Hash: 3516b252f4e32d6c5bb8
Time: 8693ms
chunk    {0} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 160 kB {4} [initial] [rendered]
chunk    {1} main.bundle.js, main.bundle.js.map (main) 5.95 kB {3} [initial] [rendered]
chunk    {2} styles.bundle.js, styles.bundle.js.map (styles) 10.5 kB {4} [initial] [rendered]
chunk    {3} vendor.bundle.js, vendor.bundle.js.map (vendor) 1.88 MB [initial] [rendered]
chunk    {4} inline.bundle.js, inline.bundle.js.map (inline) 0 bytes [entry] [rendered]

WARNING in Circular dependency detected:
src\app\app.module.ts -> src\app\app.component.ts -> src\app\app.module.ts

WARNING in Circular dependency detected:
src\app\app.component.ts -> src\app\app.module.ts -> src\app\app.component.ts

It is important to detect and eliminate circular dependencies because leaving them in might lead to Maximum call stack size exceeded errors, or imports being undefined at runtime.

To remove these warnings from your project you can factor out the circular dependency into a separate module.

For instance, if module A imports foo from module B, and module B imports bar from module A, it is enough to extract foo into module C.

You can turn off these warnings by running ng set apps.0.hideCircularDependencyWarnings=true. This will add the "hideCircularDependencyWarnings": true value to your .angular-cli.json and disable the warnings.

Fix #6309
Fix #6739

@filipesilva filipesilva requested review from hansl and Brocco June 27, 2017 09:39
@filipesilva filipesilva force-pushed the circular-dep branch 3 times, most recently from 91a1da0 to db0f817 Compare June 27, 2017 10:58
Brocco
Brocco previously approved these changes Jun 27, 2017
Circular dependencies, like `app.module.ts` importing `app.component.ts` which in turn imports `app.module.ts`, now display a warning during builds:

```
kamik@T460p MINGW64 /d/sandbox/master-project (master)
$ ng build
Hash: 3516b252f4e32d6c5bb8
Time: 8693ms
chunk    {0} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 160 kB {4} [initial] [rendered]
chunk    {1} main.bundle.js, main.bundle.js.map (main) 5.95 kB {3} [initial] [rendered]
chunk    {2} styles.bundle.js, styles.bundle.js.map (styles) 10.5 kB {4} [initial] [rendered]
chunk    {3} vendor.bundle.js, vendor.bundle.js.map (vendor) 1.88 MB [initial] [rendered]
chunk    {4} inline.bundle.js, inline.bundle.js.map (inline) 0 bytes [entry] [rendered]

WARNING in Circular dependency detected:
src\app\app.module.ts -> src\app\app.component.ts -> src\app\app.module.ts

WARNING in Circular dependency detected:
src\app\app.component.ts -> src\app\app.module.ts -> src\app\app.component.ts
```

It is important to detect and eliminate circular dependencies because leaving them in might lead to `Maximum call stack size exceeded` errors, or imports being `undefined` at runtime.

To remove these warnings from your project you can factor out the circular dependency into a separate module.

For instance, if module A imports `foo` from module B, and module B imports `bar` from module A, it is enough to extract `foo` into module C.

You can turn off these warnings by running ng set apps.0.hideCircularDependencyWarnings=true. This will add the "hideCircularDependencyWarnings": true value to your .angular-cli.json and disable the warnings.

Fix angular#6309
Fix angular#6739
Copy link
Contributor

@Brocco Brocco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for adding the option to disable/suppress this check.

@filipesilva filipesilva merged commit 1f3738b into angular:master Jun 27, 2017
@filipesilva filipesilva deleted the circular-dep branch June 27, 2017 15:30
@Splaktar
Copy link
Member

Splaktar commented Jun 28, 2017

This is good stuff! However, if I do the following steps, I get an error:

  1. ng new tmp
  2. cd tmp
  3. ng serve -> yay it works
  4. ng eject
  5. npm i
  6. npm start -> boom
> tmp@0.0.0 start /Users/splaktar/Git/angular/tmp
> webpack-dev-server --port=4200

module.js:471
    throw err;
    ^

Error: Cannot find module 'circular-dependency-plugin'
    at Function.Module._resolveFilename (module.js:469:15)
    at Function.Module._load (module.js:417:25)
    at Module.require (module.js:497:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/Users/splaktar/Git/angular/tmp/webpack.config.js:4:34)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)

Running npm i --save-dev circular-dependency-plugin seems to fix it, but ideally after ng eject things should 'just work'.

@filipesilva
Copy link
Contributor Author

@Splaktar you're right, I forgot to add it to the list of dependencies that are added to the package.json. Will do it in a followup PR.

filipesilva added a commit that referenced this pull request Jun 29, 2017
Flag is now positive instead of negative and shorter, and can now be set on commands as well (`--show-circular-dependencies`).

Dependency was also added to eject as per #6813 (comment).
filipesilva added a commit that referenced this pull request Jun 29, 2017
Flag is now positive instead of negative and shorter, and can now be set on commands as well (`--show-circular-dependencies`).

Dependency was also added to eject as per #6813 (comment).
filipesilva added a commit to filipesilva/angular-cli that referenced this pull request Jun 29, 2017
Flag is now positive instead of negative and shorter, and can now be set on commands as well (`--show-circular-dependencies`).

Dependency was also added to eject as per angular#6813 (comment).
hansl pushed a commit that referenced this pull request Jun 29, 2017
Flag is now positive instead of negative and shorter, and can now be set on commands as well (`--show-circular-dependencies`).

Dependency was also added to eject as per #6813 (comment).
@colas74
Copy link

colas74 commented Jul 26, 2017

I wonder why I get this warning if I just import classes in order to have types, I'm using cli (v1.3.0-rc.0)

export abstract class AbstractLockableEntity {
  protected abstract formLocker : FormLockerComponent;
...

and in another file I have :

@Component(...)
export class FormLockerComponent {
  @Input() formInstance : AbstractLockableEntity   = null;
...

This get me:

Circular dependency detected:
lockable-entity.abstract.ts -> form-locker.component.ts -> lockable-entity.abstract.ts

cc @Brocco @filipesilva

@elvisbegovic
Copy link
Contributor

@colas74 weird... it seems to me in java this is allowed, donno if it's cli or ts error.

@filipesilva
Copy link
Contributor Author

@colas74 you have a warning because the imports you are using as circular. It doesn't really matter if it's for types or not (as far as detection is concerned).

@istiti you're absolutely right that it's allowed in many languages, and it's perfectly allowed in JavaScript as well. It's just that sometimes Webpack has problems with it (like the ones I marked fixed in the PR).
So the warnings are mostly to let you know about something that the build system itself (not the language) has problems with.

If you don't have any problems with your imports, feel free to go ahead and disable the warnings. But if you come across those errors, you can enable the warnings again and that might give you and idea of where the problem is.

@colas74
Copy link

colas74 commented Jul 27, 2017

@filipesilva Thx for your answer. I think there is no problem to import types and create circular dependencies, if they are only used for object's type. In any case, it is not seems to create performances issue

@elvisbegovic
Copy link
Contributor

According to:

So the warnings are mostly to let you know about something that the build system itself (not the language) has problems with.

Javascript will works , but build system can have problem? So it's maybe one reason why ng build --prod Thake a while at 92% ?

@filipesilva
Copy link
Contributor Author

The 92% thing is webpack resolving sourcemaps and I think module names? Maybe that's also when it actually assembles the bundles. To be honest I'm not 100% sure what's it's doing at that phase I just know it takes a while. It's outside the CLI control per se.

@mizi-lin
Copy link

Can't add property hideCircularDependencyWarnings, object is not extensible

@dwulfde
Copy link

dwulfde commented Sep 5, 2017

@amily4555 try ng set defaults.build.showCircularDependencies=false
The option was moved

@rubenCodeforges
Copy link

rubenCodeforges commented Sep 20, 2017

And i guess it is now a issue.

Let assume we have this classes :

@Injectable()
export class ClassA {
    public static readonly STATIC_CONST_VALUE: string = "ILL NEVERE CHANGE";
    
    consturctor(private classB: ClassB){}
    
    public illCallClassBMethod(): void {
        this.classB.doSomething();
    }
}

export class ClassB {
    public doSomething() {
        // Some logic that requires a static field from classB
        console.log(ClassA.STATIC_CONST_VALUE);  //this will be now a circular dep, but its just a call to a class not a instance
    }
}

This will throw a warning now , i guess the way the plugin works , its checking the imports.
Which is not correct, the ClassA.STATIC_CONST_VALUE is a static field and should be accessed from everywhere without a problem and is not violating any OOP or DI rules.

The feature is good , no doubt , but i would suggest to turn it off by default.

dond2clouds pushed a commit to d2clouds/speedray-cli that referenced this pull request Apr 23, 2018
Flag is now positive instead of negative and shorter, and can now be set on commands as well (`--show-circular-dependencies`).

Dependency was also added to eject as per angular#6813 (comment).
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 12, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
9 participants