package.json per app

First of all,. just like to say thank you! I love nrwl nx and how well organized the code looks like when using nx! Also, it's awesome you folks are investing in React!

Prerequisites

Please answer the following questions for yourself before submitting an issue. YOU MAY DELETE THE PREREQUISITES SECTION.

  • [X] I am running the latest version
  • [X] I checked the documentation and found no answer
  • [X] I checked to make sure that this issue has not already been filed
  • [X] I'm reporting the issue to the correct repository (not related to Angular, AngularCLI or any dependency)

Expected Behavior

Is there a way we could have a package.json per app? If you are using docker, and would like, let's say, have an angular app running in one container, and the nest api into another container, then both containers will have to run npm install over the all the npm packages even when angular packages are only a subset of all the packages (and viceversa with nest). Additionally, if we do npm install inside the containers, huge packages like cypress will be downloaded, even if they have nothing to do with the api (nest) build. This take its toll especially when running a CI build in travis, circleci, etc (yeah, I know there is cache, but it's not 100% reliable).

Please describe the behavior you are expecting:

Would love to see every app having different package.json. Plus I think it is cleaner. Why having one package,json to rule them all? Seems very tightly coupled.

Current Behavior

What is the current behavior? There is only one package.json for all apps using nx

Failure Information (for bugs)

Please help provide information about the failure if this is a bug. If it is not a bug, please remove the rest of this template.

Context

Please provide any relevant information about your setup:

  • version of Nx used: 8.4.13
Asked Dec 13 '21 23:12
avatar comunitius
comunitius

19 Answer:

Thanks for submitting the issue.

You could create a package.json per project, and for instance use something like yarn workspaces to make npm installs relatively fast. We used to do it for one of our internal projects.

We believe in the single-version policy, where, for instance, all applications using NestJS, use the same version of NestJS. Even though it looks a bit crazy at first, we think it is beneficial. Companies like Google do it. So having one node_modules at the root is very similar to what Google does (with a single third_party).

I'll try to find sometime this week to author a guide on single-version policy, where I'll also cover how to add multiple package.json files if you decide that single-version policy doesn't work for you.

1
Answered Sep 02 '19 at 18:41
avatar  of vsavkin
vsavkin

Thanks @vsavkin

We love the ONE package.json to rule them all approach and rather have one package.json instead of multiple.

The only reason why we have a separate package.json for our Express (GraphQL-server) app is that we need a small production node_modules for the graphql-server, without all angular dependencies etc.

Would be great if that could be part of the guide.

(each app lives in it's own docker container)

1
Answered Sep 03 '19 at 08:44
avatar  of the-ult
the-ult

Single version policy:

Fantastic, great path for most projects.

Single list of packages:

This is a little harder to deal with as @the-ult suggested. I would love to see something per-app/library that limits which packages (name only, not repeating or varying the version!) the app/library can depend on. This data could also fuel a mechanism to generate a minimal production-only package.json algorithmically when needed.

(I wonder if this might be possible today by omitting package.json from implicitDependencies in nx.dev...)

1
Answered Sep 03 '19 at 11:56
avatar  of kylecordes
kylecordes

I totally agree with the previous suggestion of generating a minimalistic package.json for production. However, we would also need a package-lock.json to prevent the runtime production app from fetching different versions than the nx workspace.

We mainly need this to get a production app that is as small as possible since it is deployed as a Google Cloud Function

1
Answered Sep 04 '19 at 17:10
avatar  of wvanderdeijl
wvanderdeijl

I'm starting to see the point about one package.json. I've had to deal with multiple lodash versions in the past and it's a pain. Having said that, just like the previous comments, I need a small package.json in production (with the package-lock.json as well) so I can build and deploy multiple small docker images/containers in production.

1
Answered Sep 05 '19 at 19:35
avatar  of comunitius
comunitius

I think having one package.json per application is useful if you want to publish your libraries or applications separately in the future. Is there anyone who has solved that problem?

1
Answered Oct 15 '19 at 12:04
avatar  of josesaranda
josesaranda

I'm following this discussion and I understand that single-version policy may be an issue for some. But for minimal node server deployments (i.e. not deploying the entire node_modules) why not simply bundle the node app?

I think it is mainly because there still tons of issues with bundle apps using nx with webpack, nestjs, typeorm, and docker.

https://github.com/nrwl/nx/issues/1518 https://github.com/nrwl/nx/issues/1393 https://github.com/nrwl/nx/issues/1010 https://github.com/nrwl/nx/issues/803 https://github.com/nrwl/nx/issues/633

Each of them is great. But using those significant parts together is terrible.

1
Answered Oct 19 '19 at 08:08
avatar  of wangzishi
wangzishi

Reading through this because I have a use-case with several "sub-applications" that are lazily loaded into a single core Angular application, and they need to be developed by independent teams. I haven't seen that particular wrench thrown in this thread yet.

While the single package.json strategy works great for a single team, I am struggling with how these large companies handle the seemingly incredible cooperation costs of having multiple teams operate with a single package.json.

I am looking for an architecture where we have a core Angular application that is comprised of several sub-applications (which is now facilitated by Nx, and previously by the vanilla Angular CLI.) I wanted each sub-application to have a private package.json to define dependencies specific to that project, while keeping globally shared dependencies (such as Angular itself) in the root-level package.json.

This dramatically cuts the cooperation costs between teams; if Project A needs this-package@1.0.0, and Project B needs this-package@2.0.0, then Project B doesn't need to petition and wait for Project A to upgrade their application to support this-package@2.0.0.

Of course, we still have the issues of "Okay, everyone upgrade to Angular N+1 on mm/dd/yyyy!", but I think having private package.jsons can remove a vast majority of related versioning issues.

This all works fine for JIT compilation. Issues arise when you try and build it with AoT.

Is there a recommendation on how to handle this type of situation, with multiple teams working on individual sub-projects under the same global project?

1
Answered Dec 20 '19 at 14:51
avatar  of mderoche
mderoche

I like the idea of having a single master package.json file for enforcing versions across the entire repo, but I’m still struggling to understand how one creates a docker image for each app with the package.json being a subset from the master file? How do you derive an appropriate version of package.json per each app? 🤷🏼‍♂️ Obviously, I don’t need angular packages in my NestJs container and vice versa.

1
Answered Dec 22 '19 at 16:29
avatar  of demisx
demisx

I use generate-package-json-webpack-plugin to solve this problem. But I would like to generate a yarn/npm lockfile instead to tighten the dependencies but didnt find a solution for this yet.

1
Answered Dec 22 '19 at 16:47
avatar  of kraiz
kraiz

You don't need it for angular because it's webpack configuration is already making sure you only get the stuff you need into your bundle files without the need for an external runtime dependency folder (node_modules).

1
Answered Dec 23 '19 at 07:30
avatar  of kraiz
kraiz

How does Google manage to update all (i can imagine they have hundred/thousands) apps at once?

From my experience, you always get: - one app that requires too much effort/cost/time to be updated (i.e. that won't happen) - one app that needs to do something before that (i.e. delaying the update for months/years) - one app that requires to stay at some package version (angular users are often locked in older versions of TS, or some webpack users often rely on some webpack plugin which has not been migrated yet (or never will))

I'm pretty sure I didn't cover all the scenarios but they all lead to late migration / no migration at all.

Even though I agree it's important to encourage every app/team to stay up to date with the latest releases and use the same version, it becomes more and more complex over time until it's not even possible anymore.

One strategy here for nx could be to offer both options: - 1 package.json (current way) - multiple package.json (yarn workspaces way)

That being said, it's probably a lot of work to maintain both possibilities and much more work for many features.

On the other hand, keeping the yarn workspaces way and doing some checks when running nx could offer both worlds features with a limited maintenance overhead.

Whatever you decide, keep up the good work 👍

1
Answered Jan 17 '20 at 13:24
avatar  of MaximeBernard
MaximeBernard

Just following a thread and wonder if any progress has been made on this front. We are architecting a set of microservices (NestJS, React) and would love to have a package.json for each one of them as well as have a Dockerfile for each app.

Would love to hear how others have solved that?

1
Answered Feb 20 '20 at 19:48
avatar  of mikkhait
mikkhait

How does Google manage to update all (i can imagine they have hundred/thousands) apps at once?

From my experience, you always get:

  • one app that requires too much effort/cost/time to be updated (i.e. that won't happen)
  • one app that needs to do something before that (i.e. delaying the update for months/years)
  • one app that requires to stay at some package version (angular users are often locked in older versions of TS, or some webpack users often rely on some webpack plugin which has not been migrated yet (or never will))

I'm pretty sure I didn't cover all the scenarios but they all lead to late migration / no migration at all.

Even though I agree it's important to encourage every app/team to stay up to date with the latest releases and use the same version, it becomes more and more complex over time until it's not even possible anymore.

One strategy here for nx could be to offer both options:

  • 1 package.json (current way)
  • multiple package.json (yarn workspaces way)

It seems to me that you could have an automated package-pruning step using something like https://www.npmjs.com/package/depcheck, and generate per-deployment package.json files at will. My ideal flow would be the current nx approach while developing, but then when I create a docker image to deploy some app, it would traverse the dependencies and produce a minimal package.json for that app image.

1
Answered Mar 17 '20 at 13:34
avatar  of gavindoughtie
gavindoughtie

Has anyone found any clean solution on this? It's the only thing stopping from fully updating the monorepo approach :( I realize the potential and benefits the single repository gives us, however installing dependencies for 10 separate projects on every docker build is getting slower and slower..

1
Answered Mar 25 '20 at 23:11
avatar  of angelnikolov
angelnikolov

We replaced the default @nrwl/node builder with our own webpack-based node builder, which includes generating a package.json file. It's config-compatible with the @nrwl/node builder. To use:

yarn add @apployees-nx/node

Then find-and-replace @nrwl/node in workspace.json with @apployees-nx/node.

Run a build nx build myproject. Check your dist folder for package.json.

Also, if you have a package.json in the app you are building, it will be merged.

See https://github.com/Apployees/apployees-nx/#enhanced-node-builder----apployees-nxnode

1
Answered Mar 26 '20 at 01:32
avatar  of atifsyedali
atifsyedali

Don't get me wrong, I'm deeply in favor of a single repository. This does provide a unified versioning between internal dependencies. But that does not mean you need to have a unified version for your external dependencies.

You should strive for it but the bigger your repository gets, the harder it becomes until it's not even thinkable. And I'm pretty sure Google has already hit that point.

Yarn workspaces and Lerna do just that and do it well.

I'm just suggesting nx to take that approach as well so it meets everyone's needs.

1
Answered Mar 31 '20 at 10:03
avatar  of MaximeBernard
MaximeBernard

@atifsyedali You done great job, your module (schematic) does extract what the runtime needs after prod build of an app.

1
Answered Apr 17 '20 at 16:52
avatar  of manju-reddys
manju-reddys

I am a bit confused about this. It seems that different things are mixed up in this discussion.

I'll try to sort my thoughts - please comment when I got something wrong:

Monorepo: everyone here agrees a monorepo is a good thing and this is why we use nx

Dependencies: we have 2 kinds of dependencies: 1. internal dependencies: apps and libraries in the monorepo that reference each other - with nx we can directly reference the libs. Then the nx builder will take care to (re-)build what is required - i.e. we don't need to manually find the referenced libs, run the build process and install the lib in a local (or external) npm repository - nx also allows us to enforce dependency constraints between our libs - we always have only up-to-date version of internal libs (i.e. no version numbers needed)

  1. external dependencies: downloaded from the npm registry (when we execute npm install)
    • they are currently defined in a single package.json file at the project root
    • external dependencies can have different versions: see version management below

Version management I think we have 2 groups of users here. some who want to; 1. enforce that all code in the monorepo MUST use the same version of each dependency (what nx offers now) 2. have defaults versions, but still be able to override those for some libs

External dependency constraints

The features that I am missing in the current nx implementation: * we have no way to specify constraints for external dependencies: I'd like to constrain the use of external libraries
i.e. currently every lib can easily import any external dependency and there's no way to forbid this.
So a client-lib (e.g. for angular) can accidentally import a huge lib which is only meant to be used on the server-app (e.g. node-js). * another disadvantage of the single package.json file is that the IDEs will always suggest all code in every lib: e.g. for auto-import, code-completion, etc. * if we had multiple package.json files (e.g. the lerna way), then the IDE will find the nearest package.json file and only suggest the "allowed" code

I must admit that I don't have too much experience with nx, npm, yarn, lerna, etc..
But ideally, we'd have one configuration to specify all external dependencies and their versions and per lib a config to specify the allowed external dependencies for this lib (version should be optional: when not set, use the default, otherwise override it).
Then maybe the package.json files can be generated from this config - or maybe we can have an EsLint rule to enforce it?

BTW: Just a hint to the some people who mentioned that they want to have multiple package.json files to reduce the production node_modules folder: you may want to check out the ncc compiler: it can build a single js file which includes your code and only the required parts of the node_modules (and you can optionally minify the output to make it even smaller)

1
Answered Apr 25 '20 at 08:56
avatar  of tmtron
tmtron