[RRFC] npm install --from-lockfile
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 777
- Forks
- 267
- PR merge metrics
- No merged PRs in 30d
Description
Motivation ("The Why")
Based on the discussion on npm/cli#564, npm/feedback/discussions/340 and a few other issues.
The purpose of this proposal is to offer a middle ground between npm install and npm ci, providing the speed benefits of partial installs (npm install with an existing node_modules folder) alongside (some of) the deterministic guarantees of npm ci (exact package numbers and dependency numbers from package-lock.json).
Example
-
At my current workplace, we run continuous deployment on a server for testing purposes. We have a large dependency tree with multiple dependencies that require
node-gypcompilation.We do not use
npm ci; the clean install process takes longer than we would like. We would like to push changes and very quickly get results back from the server. Additionally, because we are not building production builds, we are not concerned with doing a clean, completely deterministic install every time. We don't need that level of accuracy for a test server.However, we are interested in forcing our test server to respect
package-lock.json. We have run into multiple failed builds that were the result of minor/bugfix package updates that automatically happened during a push. So ideally, we would be able to keep the speed ofnpm install, while respectingpackage-lock.jsonduring the install. -
We are onboarding a contractor to look over the codebase, or we have an Open Source project that we are writing compile instructions for. The contractor/contributor should use
npm ciafter they pull our repo, so we know they're getting all of the correct versions. However, even when writing documentation about how to download or install a repo, a contractor/contributor might forget to runnpm ci. They might not even know the command exists. In the case of a contributor, they might turn around a file an issue or complain that the project isn't compiling.We'd like to be able to specify that
npm installshould use--from-lockfilein our project's.npmrc, which would completely mitigate the above issue. -
One way we might decide to approach the above situations is by specifying exact versions of each package in our
package.json. However, this would block us from being able to use wildcards and fuzzy package numbers to help with guiding the upgrading of packages. Additionally, contributors would need to remember to only install exact versions or to updatepackage.jsonwith exact numbers whenever they install a new package. In my experience, they often forget to do so.We'd like to be able to get the general behavior of using exact package numbers in our
package.jsonwithout losing all of the benefits of fuzzy matching during package upgrades, and without complicating package installation.
How
Current Behaviour
There are two basic ways to install packages in NPM: npm install and npm ci:
A) npm install reads packages from package.json, which allows packages to be updated behind the scenes.
B) npm ci reads from package-lock.json, which allows much greater confidence that packages will not change behind someone else's back.
C) npm install allows partial installs: if a package is already up to date in node_modules, it will not be re-downloaded/compiled.
D) npm ci deletes the node_modules folder every run, forcing a clean install. This means every package will run its pre-install scripts, get copied over to node_modules, etc...
This comment on the original issue goes into a bit more detail, but the basic gist is that a full clean install is too slow for many non-production settings as soon as large packages with complicated pre/post-install scripts come into play. However, allowing non-production builds to grab the latest versions of dependencies is not reliable enough behavior for most environments.
Desired Behaviour
npm install --from-lockfile behaves according to B) and C) in "Current Behavior" above, while avoiding behavior A) and D).
from-lockfilereads frompackage-lock.jsonor another shrinkwrap for exact package numbers.from-lockfiledoes not removenode_modules.from-lockfileis ignored when installing new packages.from-lockfilewill error out if apackage-lock.jsonor other shrinkwrap is not present.npm install --from-lockfileis not a clean install. If an existing installed module is corrupted or edited beyond the point where a normalnpm installwould catch it, it will not be cleared out and reinstalled. It does not offer the same deterministic guarantees thatnpm cioffers.
This specific solution/behavior is loosely based off of @jdussouillez's comment and @DanielRuf's comment that both encouraged adding a new flags to npm install instead of npm ci.
It deviates from their offered solutions in that it does not go all the way and add a --clean option to npm install, nor does it try to alias npm ci to npm install --from-lockfile --clean. I think those are reasonable solutions, but I'm just trying to make the smallest change possible that will make all of the desired behaviors possible without messing with npm ci at all.
I think it's a much safer, smaller, more predictable change to add a single flag to npm install rather than to try and mess with existing behavior in a way that would possibly be a breaking change.
References
I have a basic implementation in progress at danShumway/cli/commit/bc8ef2.... Assuming no other changes, I still need to add a few more unit tests and I still need to add documentation. But of course, that's all subject to whether or not the implementation/proposal itself still requires work.
From my very basic testing, this seems to be working and comes with a pretty substantial performance increase in the scenarios I describe above.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Review the proposed implementation at the linked danShumway/cli commit first, then inspect the npm CLI install behavior it changes. Add the remaining unit tests and documentation mentioned in the issue, and verify the requested lockfile-based partial-install behavior and its stated edge cases.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- cli, devtools
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100