In a package.json
file, version range modifiers define
how npm resolves the versions of a dependency to install. These
modifiers allow flexibility in specifying the range of acceptable
versions. Here's a detailed explanation of each modifier, along with
examples:
=
in some
contexts, though rarely used in package.json
).
{
"dependencies": {
"lodash": "4.17.21"
}
}
4.17.21
of lodash
will be installed.
^
)0.x.x
or x.x.x
, rules differ
slightly:
0.x.x
: Only patch updates are allowed.x.x.x
: Any version is allowed. {
"dependencies": {
"lodash": "^4.17.0"
}
}
4.17.0
, 4.17.1
,
4.18.0
, but not 5.0.0
.
~
) {
"dependencies": {
"lodash": "~4.17.0"
}
}
4.17.0
, 4.17.1
, but
not 4.18.0
or 5.0.0
.
>
)
{
"dependencies": {
"lodash": ">4.17.0"
}
}
4.17.1
, 4.18.0
,
5.0.0
, etc.
>=
)
{
"dependencies": {
"lodash": ">=4.17.0"
}
}
4.17.0
, 4.17.1
,
4.18.0
, 5.0.0
, etc.
<
)
{
"dependencies": {
"lodash": "<4.17.0"
}
}
4.16.0
, 4.15.0
, etc.
<=
)
{
"dependencies": {
"lodash": "<=4.17.0"
}
}
4.17.0
, 4.16.0
, etc.
*
) {
"dependencies": {
"lodash": "*"
}
}
lodash
.-
)
{
"dependencies": {
"lodash": "4.16.0 - 4.17.0"
}
}
4.16.0
, 4.16.1
, …,
4.17.0
.
x
or .*
)
{
"dependencies": {
"lodash": "4.x"
}
}
4.0.0
, 4.1.0
, …, but
not 5.0.0
.
)
{
"dependencies": {
"lodash": ">=4.16.0 <4.18.0"
}
}
4.16.0
to 4.17.x
, but
not 4.18.0
.
||
)
{
"dependencies": {
"lodash": "<4.16.0 || >=4.17.0"
}
}
4.16.0
or
4.17.0
and above.
These range modifiers provide flexibility and control, allowing developers to define dependencies in a way that balances stability and the ability to receive updates.
The logical AND (&&
) operator in
the context of version ranges in package.json
specifies
that all conditions must be satisfied for a package
version to be considered valid.
In the Semantic Versioning (semver) specification, it
is not explicitly supported to use
&&
as a range operator directly in
package.json
. Instead, semver uses
space-separated ranges, which function like a logical
AND. This means both conditions need to be true.
When you specify multiple conditions separated by a space, only versions that satisfy all conditions are allowed.
{
"dependencies": {
"lodash": ">=4.16.0 <4.18.0"
}
}
This means:
lodash
versions must be
>=4.16.0
(greater than or equal to
4.16.0
) AND
lodash
versions must be <4.18.0
(less
than 4.18.0
).
4.16.0
4.17.5
4.17.9
4.15.0
(fails >=4.16.0
)4.18.0
(fails <4.18.0
)5.0.0
(fails <4.18.0
)
In most programming languages, &&
is the explicit
logical AND operator. While semver doesn't use
&&
directly, its
space-separated ranges effectively implement the same
behavior.
Programming Logical AND:
if (x >= 10 && x < 20) {
console.log("x is valid");
}
Semver Logical AND:
{
"dependencies": {
"package-name": ">=10 <20"
}
}
Both mean "x must be greater than or equal to 10 AND less than 20."
Semantic Versioning (often abbreviated as
SemVer) is a versioning system for software that
conveys meaning about the underlying code and its changes. It follows
a MAJOR.MINOR.PATCH
format, where each
segment has a specific purpose:
MAJOR.MINOR.PATCH
Example:
1.0.0
→ 2.0.0
(breaking changes
introduced)
Example:
1.0.0
→ 1.1.0
(added a new feature)Example:
1.0.0
→ 1.0.1
(bug fix or small change)
Initial Development (0.x.x
):
MAJOR
is often
set to 0
.
0.1.0
, 0.2.3
.Backward Compatibility:
Pre-release Versions:
1.0.0-alpha.1
or 1.0.0-beta
).
Example:
1.0.0-alpha
→ 1.0.0-beta
→
1.0.0
1.0.0+build.001
).
Version | Description |
---|---|
1.0.0 |
Initial stable release. |
2.0.0 |
Removed a key feature, breaking compatibility. |
Version | Description |
---|---|
1.0.0 |
Initial stable release. |
1.1.0 |
Added new functionality, no breaking changes. |
1.2.0 |
Added more features. |
Version | Description |
---|---|
1.0.0 |
Initial stable release. |
1.0.1 |
Fixed a minor bug. |
1.0.2 |
Fixed another bug. |
With Semantic Versioning, managing dependencies and upgrades becomes more systematic and predictable.
To create and manage different release channels for an npm package
(like @canary
, @beta
, or
@stable
), you can use dist-tags in npm.
These tags allow you to label specific versions of your package,
making it easy for users to install different versions based on their
stability or purpose.
Here’s a step-by-step guide:
When publishing a package, you can specify a tag using the
--tag
option:
npm publish --tag <tag>
Example:
npm publish --tag canary
npm publish --tag beta
Users can install specific versions by appending
@<tag>
to the package name:
npm install <package-name>@<tag>
Example:
canary
version: npm install my-package@canary
beta
version: npm install my-package@beta
You can view, add, update, or remove tags using the
npm dist-tag
command.
To see all the dist-tags for a package:
npm dist-tag ls <package-name>
To associate a specific version with a tag:
npm dist-tag add <package-name>@<version> <tag>
Example:
1.2.3
as canary
: npm dist-tag add my-package@1.2.3 canary
To delete a tag:
npm dist-tag rm <package-name> <tag>
Example:
npm dist-tag rm my-package canary
When you publish a package without specifying a tag, it is tagged as
latest
by default. You can also manually set the
latest
tag to point to a specific version:
npm dist-tag add <package-name>@<version> latest
pre-release
Versions
For pre-release versions (e.g., 1.0.0-beta.1
), you can
use Semantic Versioning with hyphen-separated
pre-release identifiers. These are often combined with dist-tags for
better version management.
Example Workflow:
npm publish --tag beta
This might create a version like 1.0.0-beta.1
.
npm publish
This might create a version like 1.0.0
.
Let’s say you maintain my-package
with these versions:
2.0.0
(tagged as latest
)2.1.0-canary.3
(tagged as canary
)
2.1.0-beta.2
(tagged as beta
)Commands to Manage Tags:
npm publish
npm publish --tag beta
npm publish --tag canary
How Users Install:
npm install my-package
npm install my-package@beta
npm install my-package@canary
By using dist-tags, you can manage multiple release
channels (e.g., latest
, beta
,
canary
). This is particularly useful for providing
cutting-edge features for early adopters while maintaining stable
versions for general users.