After reading the documentation, I still don't have a clear idea about this.
Let's say I specify
"dependencies": {"some_package": ^3.1.1}
in my package.json, and the latest compatible (i.e. consistent with the semantic versioning declared above) version of some_package is actually 3.4.9. If I were to run npm install, would that automatically install version 3.4.9?
You can use the npm semver calculator to determine what version will be installed. Where it says to enter a range, enter ^3.1.1. Since I don't know what some_package is, I can't check myself, but you can.
To understand ranges that start with a caret (^), read the semver doc. Caret means "install the most recent version that doesn't change the left-most non-zero digit". So ^3.1.1 means "install the latest 3.x version". So, yes, it will install 3.4.9 or later if they are available.
Related
what is the best practice to upgrade the dependency v-calendar from beta to the latest version v2.3.0?
I know the question is opinion based, but I am new to the field, what are the pros and cons of the way to do the upgrade.
We use "v-calendar": "~1.0.0-beta.14" in production. The latest version is currently v.2.3.0
I can think of two ways:
update to the latest version with yarn add v-calendar#latest?
upgrade incrementally until the latest version is reached with yarn upgrade "v-calendar"?
What should I do to reach the latest version? thank you
ps. we are using vue: ~2.6.10
Unless the package you are using has an upgrade guide (99.99% of them don't), there is absolutely no point in doing an incremental upgrade. If it has an upgrade guide, read and follow its instructions.
The easiest way to upgrade is to change the package version to latest (in most IDE's if you press Ctrl/Cmd and hover the package number shown in package.json a tooltip will show you currently installed version, latest wanted version and latest available version). After you changed it (by typing the latest version in), run yarn install.
In the vast majority of cases, that's all you need to do, because most packages are built with backwards compatibility (existing features remain and new features are being added). If that's not true in your case, you'll have to reimplement it following their documentation. Typically it's no big deal.
Also, note there is no risk in attempting to change to a newer version. If things break, you just go back to package.json, change version back to lower, run yarn install again and everything is back to square one.
Consider having library (e. g. NPM package) with these versions:
1.0.0
1.0.2
1.1.0-prerelease
If I specify ^1.0.0 in my dependencies, what will be version that will be installed? 1.1.0-prerelease is the latest version, but I don't think any pre-release version satisfies range where I don't specify pre-release part. I have tried using https://semver.npmjs.com, but lodash doesn't have a situation where pre-release was also latest.
Typically a range with a caret (^) prefix such as ^1.0.0 does not result in the prerelease version 1.1.0-prerelease being installed.
So given the examples provided in your question the version that will typically be installed is 1.0.2.
Note: However, that logic may not always be the case - I'll explain why shortly.
Example of typical logic using the Semver Calculator:
At time of writing this, a better example to illustrate the typical logic using the Semver Calculator is to test using typescript instead of lodash.
Using the semver calculator:
Pick typescript as the package
Enter a range of ^4.0.0
As you can see it selects 4.0.2 and does not select 4.2.0-dev.20201204 (which was published to the npm registry after 4.0.2). This logic is typically what will happen.
When may the typical aforementioned logic differ:
You'll, have noticed that in my previous explanation I say "typically" alot. I say that because npm has a dist-tag feature that allows the publisher of a package to modify the distribution tags. A short excerpt from the documentation for dist-tag reads as follows:
By default, the latest tag is used by npm to identify the current version of a package, and npm install <pkg> (without any #<version> or #<tag> specifier) installs the latest tag. Typically, projects only use the latest tag for stable release versions, and use other tags for unstable versions such as prereleases.
So, if we consider again the typescript example described in the previous section. If the publisher associated the latest tag in the npm registry with version 4.2.0-dev.20201204. For example if they run the following command:
npm dist-tag add typescript#4.2.0-dev.20201204 latest
then version 4.0.2 will not be installed (given a semver range of ^4.0.0), and instead version 4.2.0-dev.20201204 will be installed.
Similarly, given the examples provided in your question, if we were to associate the latest tag with version 1.1.0-prerelease (using the npm dist-tag ... command), and given a range specified as ^1.0.0 in the dependencies section of your package.json, then version 1.1.0-prerelease will be installed and not 1.0.2.
Note: I would consider these scenarios described in this section as quite rare, (they're certainly not typical but useful to understand), because as stated in that previous excerpt from the docs:
Typically, projects only use the latest tag for stable release versions
Additional info:
Utilize the npm view command to discover information about a package(s) dist tags, particularly the latest tag. For example:
The following command prints all tag information for the typescript package:
npm view typescript dist-tags
The following command prints the version associated with the latest tag for the typescript package:
npm view typescript dist-tags.latest
For further info about distribution tags refer to adding dist-tags to packages.
Given the news that npm 5.7.0 had some issues in production, I'm wondering if it's possible to blacklist a package version either in package.json or on the machine level perhaps in .npmrc or .yarnrc.
The behaviour I'm expecting is that upgrades are possible, so this is not a fixed semver version. SemVer has intentionally avoided defining version skipping in the spec because,
SemVer is meant to communicate what type of changes have occurred, not
'how much' change has occurred. If a user wants to know the details of
how much has changed, they should look at the changelog. A long
changelog tells them it's a big update.
But as a user I may know beforehand that I never want this version. For example, never use 5.7.0 but 5.7.1 is ok.
If you have package A that depends on B and B has a known bad version, you can define a version range with a hole in it. See last paragraph of https://docs.npmjs.com/misc/semver. I am not aware of any way to globally black-list such a version on your system however, so if you install A and it doesn't have a version hole on its dependency on B, you might have gotten the bad version, but in the example you state above, the offending version was pulled from publication as the news was released regarding the defect.
One thing you can do is purge your cache of any bad package versions to insure that they can't be used to resolve dependencies.
We're using NodeJS for some projects and are faced with an issue that must have a simple solution (seeing as nobody else seems to have the problem).
In the packages.json there are a bunch of dependencies mentioned with a minimum version, each of which may have overlapping dependencies of their own. The default way a dependency is added is using the ^ operator which seems to mean 'compatible with' or 'same major version, but minor versions may differ'.
The way I understand npm to work is on npm install to take the highest minor version available that matches. Unfortunately 'compatible with' is not quite as enforced as you'd hope.
The situation this puts us in is that for instance on a developer machine version 1.1.0 is installed, but between development and publishing a new version 1.2.0, that has a bug, is introduced. On our build machine a fresh build is made which ends up using 1.2.0 and we've introduced a bug that wasn't there in development.
We tried changing the ^ operator to = for instance, but this gives us trouble when dependencies have subdependencies that aren't compatible with the requested version.
All in all I'm a bit confused, but this thing keeps biting us anytime something changes since the development machines don't do anything on npm install if the package is already there, but the build machine always gets fresh copies.
I know from NuGet that it always takes the lowest version that matches all combined requirements. Since this is always the same for a given set of dependencies, I much prefer this approach. Is there a way to make npm work like this too?
To answer my own question:
npm has introduced a new command npm ci which does something similar to npm install but enforces that the specific versions are used that were also used when a package was initially added by using the package-lock file.
See https://docs.npmjs.com/cli/ci for more information
After updating my NPM to the latest version (from 3.X to 5.2.0) and running npm install on an existing project, I get an auto-created package-lock.json file.
I can tell package-lock.json gives me an exact dependency tree as opposed to package.json.
From that info alone, it seems like package.json is redundant and not needed anymore.
Are both of them necessary for NPM to work?
Is it safe or possible to use only the package-lock.json file?
The docs on package-lock.json (doc1, doc2) doesn't mention anything about that.
Edit:
After some more thinking about it, I came to the conclusion that if someone wants to use your project with an older version of NPM (before 5.x) it would still install all of the dependencies, but with less accurate versions (patch versions)
Do you need both package-lock.json and package.json? No.
Do you need the package.json? Yes.
Can you have a project with only the package-lock.json? No.
The package.json is used for more than dependencies - like defining project properties, description, author & license information, scripts, etc. The package-lock.json is solely used to lock dependencies to a specific version number.
package-lock.json: records the exact version of each installed package which allows you to re-install them. Future installs will be able to build an identical dependency tree.
package.json: records the minimum version you app needs. If you update the versions of a particular package, the change is not going to be reflected here.
If your question is if lock file should be committed to your source control - it should. It will be ignored under certain circumstance.
I found it bloating pull requests and commit history, so if you see it change, do a separate commit for it.