^ in package.json to get latest version of a library - package.json

Can I use caret ^ in package json for a library and expect it to pull the latest version. For eg "express": "^2.17.1", can the caret here used to pull the latest stable version which is lets say "4.17.1"

Related

why not specify a specified version then we don't need the package-lock.json

I'm new to NPM, sorry if my questions sounds stupid. Below is my question:
Q1-
When I install a package and specify a specified version, for example:
npm install xxx#3.5.1
but why in the package.json file, it becomes:
{
"devDependencies": {
"xxx": "^3.5.1"
}
}
I know that the extra caret (the ^ character) will accept versions like 3.5.2, 3.6.0 but not 4.0.0. But I did explicitly specify that I want version 3.5.1, so why NPM still add ^ in front of the version?
Q2-
If NPM install package with version which I what users specify, then we don't need the package-lock.json file, do we? Since all versions in the package.json file are unique and unambiguous?
1.
You can add --save-exact
npm install lodash --save --save-exact - installs the latest version and saves the exact version in the dependencies in the package.json.
2.
^ and ~ is the way npm offer to you to get the latest source of dependencies. It's risky sometimes though.
Read this for more detailed explanation. https://bytearcher.com/articles/semver-explained-why-theres-a-caret-in-my-package-json/

package.json dependency caret symbol

suppose in the package.json file I have my dependencies as-as -
"dependencies": {
"moment": "^2.22.2"
}
Here, are we saying that for the package "moment" we can use any of version 2.x.x functionality( i.e. we can use the new functions provided by 2.23.2 in our app, though we installed 2.22.2 on our computer) or are we saying that anyone else who uses our code of app can use any 2.x.x version of "moment" package ?
If you set:
"moment": "^2.22.2"
the user will download almost the v2.22.2. In this case you will download the v2.24.0
If you set:
"moment": "2.22.2"
the user will download exactly that version
If you set:
"moment": "~2.22.1"
the user will download almost the v2.22.1. In this case you will download the v2.22.2
You can use the functions in v2.9.9 if and only if the module respect the semver standard.
That is true the 99.999% of times.
can we use any of version 2.x.x functionality( i.e. we can use the new functions provided by 2.9.9 in our app, though we installed 2.22.2 on our computer)
Just to avoid confusion. You will not install version 2.22.2 on your computer. By saying ^2.22.2, npm will look what is the highest version of 2.x.x and install that version. You will never install version 2.22.2. You will install version 2.24, and when moment updates its packages to 2.25.0, you will install that version. So you will always have the latest verison 2.x.x installed, so you will get the functions of 2.9.9.
are we saying that anyone else who uses our code of app can use any 2.x.x version of "moment" package ?
Yes, you can verify this by checking out package-lock.json which is created by NPM and describes the exact dependency tree. https://docs.npmjs.com/files/package-lock.json
If your package.json is version 1.0.0 and you have 2.22.2 dependency on moment, and do npm install, you will see in package-lock.
{
"name": "mypackage",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"moment": {
"version": "2.24.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
}
}
}
So everybody that installs your version 1.0.0 of your package will get moment version 2.24
why do I need to install "moment.js" again (i.e. update it) once its
installed on my computer –
You don't have to to. But the common rule is to leave node_modules out of repositories and only have package.json. So that when you publish your website to for example AWS, Azure or DigitalOcean, they will do npm install and therefore install everything, every time you publish your website.
To clarify how the flow of packages usually is
You create a package/module with specific verison
I decide to use your package
So I will do npm install (to use your package)
NPM will go through the dependency tree and install versions accordingly.
My website works and I am happy
In the meanwhile you are changing your code, and updating your package.
Few months pass and I decide to change my website. So now when I do npm install (because I updated my code), I will get your updates as well.

package.json dependency not updating ^0.0.130 to ^0.0.145 when 1.0.145 is the latest

In the package.json of my reactjs webpack project I specified the version number of a dependency that I wanted to download through a npm install as ^0.0.130 where the latest version of that dependency is 0.0.145.
But when I hit the npm install its downloading 0.0.130, not the latest version.
But when I specified the version number as ^0.0.145 its downloading the latest version of 0.0.145.
I cannot figure out why its not downloading the latest version though i used caret sign (^) with the eailer number.
Can anyone help me to figure out why this is not happening in the right way.
^0.0.145 matches the most recent ^0.x.x version
To upgrade to latest version for the 1.0.0 major release you will need to use something like^1.0.0
Yes, That can be happen.
After a component is publishing using npm publish command the latest version is usually the highest version number. But if a component is published using npm publish --tag latest that version is marked as the latest one. So though you published new versions after that the latest version will be the eariler version.
In above scenario they published 0.0.130 as the latest version using npm publish --tag latest. So though they published new versions after that, ^0.0.130 is the latest one.
0.0.145
.......
.......
.......
0.0.131
0.0.130 --------latest
0.0.129
0.0.128
0.0.127

"npm update" is installing a beta version of the module over the stable version that installed after "npm install"

Currently the npm package mongoose is on version 3.8.12. Running npm install mongoose --save correctly installs version 3.8.12 and saves the dependency to package.json as follows:
"dependencies": {
"mongoose": "^3.8.12"
}
If you look in node_modules/mongoose/package.json you can see that the installed version is indeed 3.8.12. However, if I now run npm update then npm will go ahead and install an unstable version of mongoose (3.9.0). I assume this is because of the caret in the dependency entry which tells npm to go ahead and upgrade minor versions (i.e. 3.8 to 3.9). That's fine, except I don't want any prerelease versions. If I modify the dependency and remove the caret then npm update works as expected, except of course that I now have to manually upgrade the dependency version even for minor and patch updates.
You can see from running npm info mongoose that they have a "latest" tag and an "unstable" tag.
So clearly npm install uses latest unless otherwise specified, while npm update is ignoring the tag altogether and grabbing the latest minor version it's aware of.
Is there a way to modify the dependency so npm update will pull in the latest minor version but ignore any prerelease versions?
UPDATE
Same issue occurs if I try to use 3.x.x as the dependency. I was hoping that would still allow me to upgrade through minor versions without prerelease versions but that's not the case :/
Tilde (~3.8.12) technically works but it's a bandaid. The only reason it "works" is because the breaking changes being introduced are in 3.9.0-unstable and tilde doesn't allow npm to upgrade across minor versions. If these "unstable" changes were introduced in 3.8.13-unstable then this same issue would occur even when using the tilde.
UPDATE 2
I also tried manually specifying the "latest" tag: ^3.8.12-latest. That didn't change anything; npm update ignores the tag entirely, even if it's explicitly in the dependency listing itself :/
semver does not specify a way to tell apart stable and unstable versions.
As you said the caret would allow for npm update to install any 3.x.x version, while the tilde would allow any 3.8.x version even if the next version is called 3.8.13-broken.
Sadly, the same happens with any semver operator, so there's no escape.
As you see, you are better off using the specific version 3.8.12.
I would have thought the simplest approach here would be to use the tilde ~
"dependencies": {
"mongoose": "~3.8.12"
}
The difference from the "caret" ^ being that the "tilde" will match on 3.8.x where the "caret" matches anything equal or above the specified version.
Just to update for anyone who stumbled across this like I did, I did a minor semver bump and published it tagged as beta, but in the 10-15 minutes after publishing, npm installs defaulted to this beta as latest, despite it being clearly tagged.
I think there's some lag time on updating the semver table, if you give it 10-15, your future npm install <packagename> attempts should give you the correct version.

How do specify latest point release in package.json

Within a package.json file, how do I specify that I want the latest point release version of a module, event if I still have one of the same minor version?
For example, say I have a dependency on the module var, version 1.1. I have 1.1.0 installed in node_modules already, but the module revs to 1.1.1. How do I have it so that when I run npm install again, 1.1.1 replaces 1.1.0
would it be
"bar": "1.1.X"
"bar": "~1.1.*"
"bar": "^1.1.*"
or something else all together?
Use "bar": "latest" in the package.json and when you want to update use npm update.
Use #latest for the version
npm install -S bar#latest

Resources