nrwl / nx

Smart Monorepos · Fast CI
https://nx.dev
MIT License
23.29k stars 2.32k forks source link

Using different versions of a lib or a package #309

Closed raczroland closed 4 years ago

raczroland commented 6 years ago

I want to start my next Angular project using Nrwl Nx, because I need to write multiple apps for one client. But:

  1. I read this: 'An upgrade to a lib requires a change to all implementors.' Is there any solution (bypass) to use different versions of a lib or an NPM package in different apps? There is only one node_modules, but this is critical for my apps.

  2. How can I specify different version numbers for the different apps? Usually I give a version number in package.json, but with Nx there are only one package.json for all of my apps. Should I put it in the environment files? Or in the .angular-cli.json file? I want to display the version number for the users in my apps somewhere.

I know, I should ask these questions on StackOverflow, but they want to close it, and I don't know where to ask it.

Thank you.

ThomasBurleson commented 6 years ago

@raczroland - IMO, these are good questions that we should document in a Wiki.

nweldev commented 6 years ago

I'm currently testing the use of lerna to address this, given that I should also use ng-packagr in order to permit to publish and use some libraries outside our Nx monorepository. You should be able to also use yarn worspaces for that. Linking : https://github.com/nrwl/nx/issues/87

raczroland commented 6 years ago

@noelmace: First of all, thank you for your comment. I checked that issue (lerna, workspaces) and followed this article too but still not sure how to use multiple versions of a package for different apps in one repo, if I want to use Nx too. Do you have any advice? Any results with your testing?

nweldev commented 6 years ago

@raczroland You're welcome.

In fact, after a lot of tests, both with lerna and workspaces, my conclusion is that we don't need such tools, even if we have package.json files for the libs we build with ng-packagr and publish on our npm repository.

Here is why : lerna is, in my opinion, thinked as a tools to manage different projects in a monorepository, namely with each project having is own build process and dependencies. Given such, it will create a node_modules for each workspace. This is why it is logical with lerna to have diferent dependency versions : each project could be used in a entirely different way than the others. I now think using it with Nx doesn't make sense, since Nx provide all the tools we need to have a consistent build system for every workspace.

On the other side, yarn workspaces is only a solution wich aim to manage different dependencies in a coherent way. Using it with Nx is relevant if you also use ng-packagr and have different dependencies between your projects, but there is a big cons to this : Angular don't support having two different versions of angular definitions in the same compilation.

With all this stuff in mind, I ran into a much more simple solution : as we only use libs/*/package.json to manage the ng-packagr build process, and as we want coherent dependencies versions in our monorepo, we add dependencies and peerDependencies for our libs in this package.json files, and then add them to the root package.json file, wich is used by the build process (namely Nx and some node scripts). As we use a specific node script to build and publish this specific libs, we also test that every dependency and peerDependency in this package.json files is coherent with the ones in the root package.json file before the build, and throw an exception if not.

Given the amont of work on this, I will look deeper in Nx and see if this could lead to some PRs. @vsavkin (and others), any guidance / opinion on this would be really appreciate.

nweldev commented 6 years ago

FYI @raczroland the "specific node script" I mentionned is now available, and you can see wath I talked about when I said "we also test that every dependency and peerDependency in this package.json files is coherent with the ones in the root package.json file before the build, and throw an exception if not." here : https://github.com/noelmace/packagr-for-nx/blob/v0.2.0/src/libs.js#L56

brunano21 commented 6 years ago

@noelmace @vsavkin @jschwarty Hi, I have a similar question on this topic. I have posted it on ng-packagr here in order to understand what's the best strategy. Would you mind to give your inputs, please?

jpremkumar commented 5 years ago

Any update or workaround for having a separate package.json for apps?

vsavkin commented 4 years ago

Folks, I'm going to close this issue.

We strongly discourage your having multiple versions of package.json for your packages. Single-version policy, although comes with its own problems, is one of the reasons why monorepos provide the benefits they provide.

Both npm and yarn allow you to use multiple versions of the same library. It can be useful in rare situations. It works with Nx.

You could also use Lerna or Yarn Workspaces in combination with Nx if you have to.

alirezamirian commented 3 years ago

Is there any consequences in manually creating a package.json in an app's directory and add all or a subset of its dependencies there?

IgnusG commented 1 year ago

Now that next.js 13 is out I wanted to pick it up for a new project we have but unfortunately there is another legacy project in the workspace which uses react 16 and is in the very slow process (we are talking years) of upgrading.

I know it's strongly discouraged by nrwl to have multiple lib versions but this would be super nice for gradual adoption. The 2 projects are inside a monorepo with a global package.json right now (which requires react 16) but they are otherwise independent (they are deployed separately and don't import each other) so the newer project using react 18 and nextjs 13 would be fine.

I'm struggling to find a way to nicely solve this with nx though 😔

jamesbrune commented 1 year ago

@IgnusG did you by chance happen to find a solution for this or are we riding this out together?

kievsash commented 1 year ago

I think if we have multiple projects in monorepo and legacy among them - legacy should be managed in another branch (not main, but rather main_6.x, etc). In that branch, you can have lib versions as you wish, while in another (main) branch - most up-to-date lib version. But I am curious if there are other solutions.

dvictory commented 1 year ago

@IgnusG @jamesbrune - just ran into similar issues, legacy app on next.js 12, but want to use 13 on new apps. Seems that upgrading all at same time could bring a lot of risk if you have a lot of apps running in a core platform like next.js or nest or even react. Y’all find any worthwhile solutions?

IgnusG commented 1 year ago

@dvictory @jamesbrune nothing that would be acceptable in production 😢 Since we also made the unfortunate decision to use NX runners as well, installing a different version of react/nextjs inside a project itself as suggested just does not work as the runners get confused over which version of which library to use.

Feel like this can really be solved well only with a first party solution by NX otherwise none of the ecosystem NX built can easily be used or integrated with. The problem here is really that the single version across the whole project works amazing if you are managing libraries in your repository that depend on each other but fails flat the moment you use your mono-repo to manage multiple separate apps.

sarifmiaa commented 1 year ago

We also ran into the same issue we had a legacy app in React 16 but wanted another app to use a newer version of react. The only working solution we found is connecting it with a workspace. We used pnpm workspace with its capabilities of managing node modules by using a non-flat directory structure it solves the problem of space and also having a duplicate copy of the same package. And by connecting it with nx we can use the capabilities of nx.

dvictory commented 1 year ago

Hey @sarifmiaa could you elaborate a little more on the non-flat workspace you created? And how you used pnpm? Do you use pnpm along with nx, (ie no yarn or npm at all)? Thanks

kievsash commented 1 year ago

Afai can assume @sarifmiaa just setup pnpm workspaces where each package/lib has its own package.json so now one app can use ver1 of specific package while app2 can use same thurdparty package of ver2. And nx can be setup on such workspace to bring some benefits like graph and cached builds. Just make a search on youtube: pnpm workspaces and nx

But this doesnt solve concern regarding supporting a few versions of your own lib in monorepo. Either you tag some version and use this tag in some app. And to make a fix checkout that tag, make fix, publush and cherry pick to same lib in master(which is latest). Or create another lib-old but manually syncs lib and lib-old fixes and in some time removes lib-old. So each major lib ver is actually separate lib in monorepo

PShorin commented 1 year ago

Can you help please? I have nx version 15.8.1, but my team is using version 15.8.0-beta.9. How I can return to the previous version of nx?

Inam-urRehman commented 1 year ago

I have a similar issue but this time I am using ajv ( 5.2.3 ) library for my project but NX is also using it ( latest version ). I can't upgrade ajv so any workaround for resolving this issue?

github-actions[bot] commented 1 year ago

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.