Add support for generating a package-lock.json file for each project
See original GitHub issue- I’d be willing to implement this feature (contributing guide)
Description
Currently, Nx supports the build option generatePackageJson
which is dropped into the build output (usually under dist/
). This is great, as it allows only the necessary dependencies to be installed for each application, which becomes paramount when trying to configure and deploy docker images for each app in a monorepo.
I would like to see support for package-lock.json added, so that we may perform package installs using the lock file, rather than package.json, via the npm ci
command.
Motivation
One of the drawbacks with just having package.json is that we have to run npm i
to install, which may bump versions if ^
or ~
are used in the version numbers in the dependencies. There is another wonderful command that npm has, npm ci
, which does a “clean install” by referencing ONLY package-lock.json. This will guarantee that only the exact versions of dependencies that are known to build correctly will be used when building in any other environment. An added benefit of using npm ci
is it can and usually is faster than npm i
as it does not have to search for and determine IF there are newer packages to be installed…it installs exact versions, and can do so as quickly as possible, using any configured caching mechanisms optimally, etc.
Using npm ci
has become standard for me anywhere outside of my own local. In fact, when I first clone a repo onto a new machine, I will use npm ci
to install with the same deps I had on other machines. I am an avid fan of CircleCI, which has configured their system to support near-instantaneous installs with npm ci
as well…even when you have gigs and gigs of dependencies, npm ci
can run in a matter of 20-30 seconds with a properly configured npm repo and a fast network.
I would like to leverage the same benefits of npm ci
in my Dockerfile configs for each of my apps in an nx monorepo. This will guarantee that I am installing KNOWN and TESTED packages, and never run the risk of unexpectedly updating a package to a newer and potentially broken version during image creation.
Suggested Implementation
I am not certain as to how this could be implemented. Given that the package.json that is generated has a specific list of direct dependencies, I’ve wondered if it would be possible to walk the root package-lock.json, mark each “reachable” dependency (starting with the roots from the generated package.json) and rebuild a new one with just the dependencies that are “reachable.”
Alternate Implementations
Potentially just run an npm install
in the apps dist directory after generating the app-specific package.json. The downside of this is that we could also still update packages with ~ or ^ to newer versions.
Issue Analytics
- State:
- Created a year ago
- Reactions:16
- Comments:34 (15 by maintainers)
I haven’t used it in nx, as I no longer have access to some of my old projects. But I recently reimplemented packge.json generation from a yarn monorepo, and I think I found a solution to this.
After building your project, cd into the dist folder, with your generated package json. Run,
npm i --package-lock-only
, which appears to resolve the packages in your package.json to the ones which are installed, and generates a package-lock.json.There might be some extra steps with regards to resolving properly in nx, depending on your setup. But in a yarn workspace, I haven’t found any version discrepancies between package-lock.json and yarn.lock.
Your mileage may vary, but for me, using npm ci with a package-lock.json is a clear win over no lock file at all, especially with all the package supply chain attacks these days.
@kroeder, not yet. I will add that feature probably on Monday