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

How to resolve "Circular dependency" in NRWL #2570

Closed
kswaroop opened this issue Feb 27, 2020 · 29 comments
Closed

How to resolve "Circular dependency" in NRWL #2570

kswaroop opened this issue Feb 27, 2020 · 29 comments

Comments

@kswaroop
Copy link

kswaroop commented Feb 27, 2020

I am getting the below LINT error

"Circular dependency between "A(lib)" and "B(lib)" detected (nx-enforce-module-boundaries) tslint error"
Most of the issues are coming when a Service from one Library is used(imported) in another lib.

Can you please help how to resolve this issue

@czaplej
Copy link
Contributor

czaplej commented Feb 27, 2020

U can't doing something like:
`
//LIB A
import libB from 'LIB_B'

//LIB B
import libA from 'LIB_A'
`
You create service "LIB_C" Which has methods that u used in LIB_A and LIB_B. LIB_C must be independent of LIB_A or LIB_B

@kswaroop
Copy link
Author

kswaroop commented Feb 27, 2020

Thanks, Yeah I am using in the same way, I have created a service 'LIB_XYZ which has the methods and I am using in other libraries, but still getting an error

@FrozenPandaz
Copy link
Collaborator

If you use nx dep-graph you should be able to see the circular dependency.

What @czaplej mentioned about creating a 3rd library works a lot of the time.

I wrote an initial doc in the wiki on resolving circular dependencies:

https://github.com/nrwl/nx/wiki/Resolving-Circular-Dependencies

Let me know if it helps.

@kkuriata
Copy link

kkuriata commented Mar 5, 2020

Anyway, something happened that NX started posting linter errors? I didn't change anything in my project, "only" updated from 8 to 9 and linter started throwing circular dep errors (same nx-enforce-module-boundaries settings).

@czaplej
Copy link
Contributor

czaplej commented Mar 5, 2020

I have similar errors that @kkuriata said. I have use 9.0.4 version of nx

@cngarkar
Copy link

cngarkar commented Mar 6, 2020

I think @kkuriata is right. I'm also seeing the circular dependency issues after upgrading to 9.

@kswaroop
Copy link
Author

kswaroop commented Mar 6, 2020

Thanks, Yeah I am using in the same way, I have created a service 'LIB_XYZ which has the methods and I am using in other libraries, but still getting an error

I have manually updated the code by removing which has a circular dependency, It works fine now, Actually, all libraries are interrelated, so if one has dependency most of the other related are also failing

@snebjorn
Copy link

I getting false positives of nx-enforce-module-boundaries

I have this graph

image

Where each of the akita-ng-libraries have akita as a peerDependency

I also have a demo app which uses all of the above (remember peerDependencies) which causes the graph to look like this

image

and now I'm getting spammed with false nx-enforce-module-boundaries

Circular dependency between "akita-ng-entity-service" and "akita" detected
Circular dependency between "akita-ng-forms-manager" and "akita" detected
etc

please advice

@snebjorn
Copy link

snebjorn commented Mar 13, 2020

Nevermind, I missed the arrow going from akita to the app :/

Now I'm not getting any nx-enforce-module-boundaries

image

Pretty cool tool - I must say

@dsebastien
Copy link

I'm facing difficulties understanding how to best structure my NX workspace in apps and libs to optimize build times and benefit from caching, considering an Angular + NGRX app.

As the starting point, I had one "web" app, composed of many major "features", each with its own (lazy-loaded) Angular module. Those modules were loaded lazily through the router, but also eagerly when a dependent Angular module needed it (e.g., if module X needs module Y, it has it in its imports).

As part of my current refactoring, I've extracted most of those features in separate libraries: one per major feature of the app, which I load lazily when needed.

Now, after fixing compilation issues, I remain with circular dependencies. My question is: what is your experience with splitting inter-dependent lazy-loaded Angular modules and what would be your recommendation?

Do you recommend splitting each feature in multiple libs (e.g., feature-x-core, feature-x-store, feature-x-dumb-components, feature-x-smart-components, ...)?

I've given this some thought and I don't see a clear path forward. For instance, if I consider the NGRX selectors of feature-x, then I can see that those rely on state types and selectors from feature-y.

One idea that I still have is extracting some parts (e.g., reducers & selectors) of the store for each feature and putting those in a shared "core" lib, but I'd still remain with the Angular module imports. Or should I just ignore the lint error in that case?

In our case I feel like keeping all of those features in the same NX lib is detrimental as it represents > 80% of the whole app.

@xmlking
Copy link
Contributor

xmlking commented Mar 27, 2020

Hi difficult to find why I have circular dependency! don't see any dependency from core -> webapp in the code
https://github.com/xmlking/yeti

image

@snebjorn
Copy link

@xmlking
image

@FrozenPandaz
Copy link
Collaborator

something happened that NX started posting linter errors? I didn't change anything in my project, "only" updated from 8 to 9 and linter started throwing circular dep errors

Yes, Nx is able to resolve more dependencies in 9 than before in 8. As a result, a dependency could have been resolved that now causes a circular dependency. These are valid dependencies.

For example,

Relative dependencies are now a resolved dependency even though they are not recommended.

import { } from '../../libs/libA/src'; // Is now a dependency

@FrozenPandaz
Copy link
Collaborator

I'm going to close this issue as I've started a guide.

https://github.com/nrwl/nx/wiki/Resolving-Circular-Dependencies

Please open a new issue if that guide does not cover a method for resolving circular dependencies so we can add it.

@Abdallah-khalil
Copy link

Abdallah-khalil commented Apr 12, 2020

@FrozenPandaz
I'm currently having a situation where i'm using the environment.ts file from my app into more than one library and those libraries are used in this app . which was going fine with angular 8 , but now it's showing a circular dep error . Is there a way to get a round that ?

in my tsconfig.json file i have this code added to paths
"@global-env/*": ["apps/web/src/environments/*"],

i have a library called core-data-access where i call the environment
import { environment } from '@global-env/environment';

then i import some services from the core-data-access library in my web app
#2851

@kkuriata
Copy link

kkuriata commented Apr 18, 2020

@Abdallah-khalil You should move your environment files into some common library that will be imported by all the apps you need. You can then use fileReplacements in angular.json/workspace.json to replace specific environment for chosen build. Unfortunately when you want to use fileReplacements with default dev build (ng serve), then you need to point the configuration: ng serve --configuration=serve (@FrozenPandaz not sure if it is a bug or it is inteded).

For example, when I have two projects: project1 and project2. And one lib core.

libs/core
  /environments
    /project1
      environment.serve.ts
      environment.prod.ts
    /project2
      environment.serve.ts
      environment.prod.ts
  environment.ts // this one will be replaced by any from above

Then I use angular.json to set file replacements inside serve configuration to have it by default when I develop new features. Unfortunately in this case it is not enough as I mentioned. Even when I specify file replacement for both projects, it won't work without --configuration=serve flag. But because serve is default ng serve configuration, hence I think it is a bug, but not sure.

@Ponjimon
Copy link

There's also the issue when using something like typeorm. Database entities naturally can have circular dependencies where one entity has a OneToMany relation to another entity which itself has a ManyToOne relation to the prior entity. This causes a circular dependency which then causes errors. :/ Is there any way to solve this?

@cngarkar
Copy link

I updated the nx workspace recently, and I'm no longer seeing the circular dep errors. Can someone from nx team confirm if this is fixed or still a known issue?

@hcharley
Copy link

@Ponjimon That's a very good point, and one that is keeping me (wrongly or rightly) from having multiple modules for my TypeORM entities.

@ghost
Copy link

ghost commented Jul 20, 2020

Another possible scenario, which I have encountered, is when using NgRX Router Store, like in https://blog.nrwl.io/using-ngrx-4-to-manage-state-in-angular-applications-64e7a1f84b7b

E.g.
2 libs, a UI lib and a store lib.
you set up effects in the store lib to respond to navigation to a component in the UI lib.
a component in the UI lib calls the store facade to retrieve some data that it needs.

Thus a circular dependency.
In Victor's post the components which are the subject of navigation are in the same app as the effects, etc, as it is a simple example.

@then3rdman
Copy link

Another possible scenario, which I have encountered, is when using NgRX Router Store, like in https://blog.nrwl.io/using-ngrx-4-to-manage-state-in-angular-applications-64e7a1f84b7b

E.g.
2 libs, a UI lib and a store lib.
you set up effects in the store lib to respond to navigation to a component in the UI lib.
a component in the UI lib calls the store facade to retrieve some data that it needs.

Thus a circular dependency.
In Victor's post the components which are the subject of navigation are in the same app as the effects, etc, as it is a simple example.

I have run into this exact situation! Slightly less complex however.

I am using a lib that container my auth store, its being used in the login feature lib. I want to use the navigated helper to generate a cookie when the login component is loaded however this is a direct circular dependancy.

I see no way around this.... that is if i am going to the navigated helper.....

@nhhockeyplayer
Copy link

nhhockeyplayer commented Dec 15, 2020

so it sounds like some of these circular dependencies are just saying

HE... he is using some stuff from HER
and
HER is using some stuff from HE

but as long as it executes fine there should be no problem

unless these circular dependencies are warning of an infinite loop?

I think the definition of circular dependency needs to be revisited

maybe these are just BIDIRECTIONAL ASSOCIATIONS which may be harmless

and a REAL circular dependency means INFINITE LOOP imminent

any thoughts ?

can someone elaborate simply confirming somethings I noted here ?
because the alternative to resolve all these means proliferated libs
and for large scale project this could ensue as CHAOS where everything needs to be a library
and what ensues when some library needs multiple pieces of logic already isolated in multiple libraries?

@skopekreep
Copy link

Adding to what @ghost said, it seems that a circular dependency is unavoidable when using the navigation operator in an effect, if the component that the operator references is not in the same module (or lib) as the effect.

In my case, the component communicates exclusively with a facade in a data access lib to get its data. But after switching my effect to use the router as the source of truth as recommended in the article previously cited, the effect in the the data access lib references back to the component in the ui lib. Guaranteed circular dependency. Splitting apart data access libs from ui libs isn't an anti-pattern, but perhaps there is some nuance I'm not appreciating.

Any insights or best practices are welcome. Thanks.

@nhhockeyplayer
Copy link

nhhockeyplayer commented Jun 5, 2022

Can someone elaborate a comprehensive separation solution for this?

.eslintrc.json governs my features/data-access as follows

                                "sourceTag": "type:data-access",
                                "onlyDependOnLibsWithTags": [
                                    "type:data-access",
                                    "type:environments",
                                    "type:util"
                                ]
                                "sourceTag": "type:feature",
                                "onlyDependOnLibsWithTags": [
                                    "type:data-access",
                                    "type:environments",
                                    "type:feature",
                                    "type:ui",
                                    "type:util"
                                ]

my @shared-root-data-access lib project has the following tags

  "tags": [
    "domain:shared",
    "scope:root",
    "platform:web",
    "type:data-access"
  ]

my @shared-feature-notification library has the following tags

  "tags": [
    "domain: shared",
    "scope: shared",
    "platform: web",
    "type: feature"
  ]

How can my effects send a Ionic toaster UI notification message to the UI if I am forced to separate everything with eslint?

Does anyone see a solution? I would hate to have to remodel my notifications feature with its own data-access just to get messages to the UI thru a de-coupled dispatch action but would rather just use it right in my effects.

Do I have a choice here?

Im also seeing the same twangle with services which I separated into a shared-root-service library yielding this

>  NX   Could not execute command because the task graph has a circular dependency

   shared-root-data-access:build:production --> shared-root-service:build:production --> shared-root-data-access:build:production

when my effects enjoy full usage of services & router all over the codebase

Victors book on this is awesome Im stunned its 2018 and barely any of this stuff is being applied in the field from my camp... and Im doing all I can to bring Nx to the field... and only met with indifference fear but I prototype it for every assignment to prove... tech leads have been obsoleted overnight now (by the Nx masterpiece) and stuck on what they only know and afraid to peek at.

Nx is the final way.... trying to see it all thru (the circular dependencies prevention model) I think this is the final jump more needs to be said and shown the airlines repo as generous (and thanks guys awesome push) as it was doesn't go deep enough code growth wise to actually see this play out.... with services, features getting tangles up with data-access and effects.

If everything NEEDs to be separated by de-coupled dispatches then I think I get it. But if data-access library project uses services library (which is what effects enjoy) and service library project dispatches actions (which is reasonable) ... its locked down wont compile with circular dependency.

A confirmation would be nice.

thanks in advance

@JonesHong
Copy link

JonesHong commented Oct 8, 2022

It work for me.

Same issue!!
image
image

nx dep-graph

image

But if I add "depndsOn":[]
image
image

It works
image
image

After adding this, the graph is the same.
image

It look like same problem at #9085
Good luck guys!

Here is my package.json.

  "devDependencies": {
    "@nrwl/angular": "^14.7.5",
    "@nrwl/cli": "14.7.5",
    "@nrwl/cypress": "14.7.5",
    "@nrwl/eslint-plugin-nx": "14.7.5",
    "@nrwl/jest": "14.7.5",
    "@nrwl/linter": "14.7.5",
    "@nrwl/nest": "^14.7.5",
    "@nrwl/node": "14.7.5",
    "@nrwl/nx-cloud": "latest",
    "@nrwl/workspace": "14.7.5",
    "@types/jest": "28.1.1",
    "@types/node": "16.11.7",
    "nx": "14.7.5",
    "ts-node": "10.9.1",
    "typescript": "~4.8.2"
  },
  "dependencies": {
    "@angular/core": "~14.2.0",
    "@nestjs/core": "^9.0.0",
  }

@JonesHong
Copy link

JonesHong commented Oct 8, 2022

I also try to move out the depends part.
Make Graph simple
image

I build the ngrx-like store management for both Angular and Nestjs.
File structor like this:
image
<ENTITY_NAME>.backend.effect.ts depends on @nestjs/common
image
<ENTITY_NAME>.frontend.effect.ts depends on @angular/core
image

Becuse of those depends, Nx will become circular.
So I just move out those part to their own scope.
image
backend struc
image
image
frontend struc
image
image

@JonesHong
Copy link

JonesHong commented Oct 8, 2022

I had try this too, but not work.
I was expect that it will be exclude when compile.

image
image

@jmeinlschmidt
Copy link

I was receiving false positive circular dep. error. Solution for me was to run nx reset. I think this suggestion might take part in the wiki as well https://github.com/nrwl/nx/wiki/Resolving-Circular-Dependencies, any opinion @FrozenPandaz?

@github-actions
Copy link

This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 21, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests