From 7f6e9ff1af724912f1c5343781e3ec610ab4a360 Mon Sep 17 00:00:00 2001 From: Henry Zhu Date: Thu, 10 Jan 2019 16:39:58 -0500 Subject: [PATCH] Ratify 0008-no-caret-prerelease-installs.md (#14) * Create 0002-no-caret-prerelease-installs.md * Update 0002-no-caret-prerelease-installs.md * add implementation details * Rename 0002-no-caret-prerelease-installs.md to 0008-no-caret-prerelease-installs.md --- 0008-no-caret-prerelease-installs.md | 47 ++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 0008-no-caret-prerelease-installs.md diff --git a/0008-no-caret-prerelease-installs.md b/0008-no-caret-prerelease-installs.md new file mode 100644 index 000000000..00e4be219 --- /dev/null +++ b/0008-no-caret-prerelease-installs.md @@ -0,0 +1,47 @@ +# No Caret Ranges for Prerelease Installs + +## Summary + +This proposal changes the default behavior of the install command to pin the package version, but only for a package that is tagged with a version that is a [prerelease](https://github.com/npm/node-semver#prerelease-tags) (and not add the [caret range](https://github.com/npm/node-semver#caret-ranges-123-025-004), `^`) + +```sh +# if this resolves to a prerelease such as 7.0.0-beta.52 +npm install @babel/core +``` + +results in + +```diff +"devDependencies": { +- "@babel/register": "^7.0.0-beta.52" ++ "@babel/register": "7.0.0-beta.52" +} +``` + +## Motivation + +As mentioned in the `node-semver` [readme](https://github.com/npm/node-semver#prerelease-tags), package authors may intentionally use prerelease tags to signify instability and breaking changes (`-alpha`, `-beta`). + +However, when a user tries to install a package like `@babel/core` from the cli with `npm install`, the default behavior of `--save` or `--save-dev` to `package.json` applies the `^` in front of the version which will install the latest prerelease in subsequent installs. + +This may be an unexpected experience for end users, as they may not realize they have installed the prerelease version initially, or don't understand that a package author maybe in the midst of other breaking changes that a user would not want to automatically have to deal with on CI or locally. + +*Example issue*: https://github.com/babel/babel/issues/7786#issuecomment-383586020 + +By changing the default behavior to pin to the latest version, a user won't be automatically opted into the latest version and will have to explicitly do it themselves. This way an end-user can decide when to upgrade. + +## Detailed Explanation + +`npm install`, when writing to `package.json` (like with `--save` or `--save-dev`), should check with semver and only add the `^` if the version isn't a prerelease. I don't believe it should affect anything else. + +## Rationale and Alternatives + +One alternative is for package authors to not actually use prerelease versions at all: they might always stick to a `0.x` versioning system, or only make major version bumps. + +Otherwise, each time someone reports an issue with different/incompatible versions the package author would tell them to change their `package.json` to remove `^`. + +## Implementation + +See `Detailed Explanation`. Add another conditional when writing to `package.json` on `npm install` such that it uses `semver` to check if the version passed to `npm install` is a prerelease or not. + +Suggestion: modify https://github.com/npm/cli/blob/ab0f0260e5b6333f98062fb2d9f4f9954d3ee6cd/lib/install/deps.js#L303-L305 and add a conditional like `semver.prerelease(version) == null`