How Does npm --save Decide Which Version and SemVer Options? - npm

If I type the following into my computer
$ echo '{}' > package.json
$ npm install pug --save
and then look at my package.json, I'll see that npm added a dependency for me.
#File: package.json
{
"dependencies": {
"pug": "^2.0.0-rc.1"
}
}
Sweet! However -- how does npm decide to grab version 2.0.0-rc.1? And how does npm decide to use the ^ SemVer version modifier?
As a user of npm can I configure or tell it to use a different SemVer modifier and/or download a different version? (both a specific version and/or something like "latest stable")
As an npm package maintainer, can I specify that npm's default behavior should be something other than "grab the latest version and slap a ^ on there"?

npm takes the latest tag publicly available and ^ is the default, you can use save-prefix to change it locally.
To a get specific version use #version after package name i.e. npm install pug#0.1.0.
Something like composer's minimum-stability doesn't exist in npm world.
As a maintainer, you can't do anything, except keeping SemVer and writeing good code :)
But at all package.json is just a JSON, you can simply modify them, without using any CLI commands and define whatever you need.

Related

NPM equivalent for "npm:#user/package-name" version in package.json?

I saw this in a package.json file:
"react-native-wheel-picker": "npm:#gregfrench/react-native-wheel-picker",
That doesn't match the tarball, http, or git dependency formats documented in the NPM docs. Looks like it's a yarn convention, because running yarn installed that dependency without complaints from the start script (which otherwise would complain warn Package react-native-wheel-picker has been ignored because it contains invalid configuration. Reason: Cannot find module 'react-native-wheel-picker/package.json').
What does that "version" string mean, why not use "#gregfrench/react-native-wheel-picker" directly, and what would be the package.json equivalent that would allow npm to function correctly?
The npm compatible dependency specification would look like following:
"#gregfrench/react-native-wheel-picker": "<version>"
As I see on npmjs.com the latest version for #gregfrench/react-native-wheel-picker is 1.2.3 so if the latest version is needed than following should be in the package.json:
"#gregfrench/react-native-wheel-picker": "1.2.3"
If you don't want to have an exact version there are some possibilities like using ^,~, >=.. characters with the version string. These possibilities are documented here.

Package.json pasting a package name in bad?

What happens differently when you go into your package.json and paste a package name in and do npm i vs. doing it the real npm i package-name?
package.json:
"dep": 1.0.0
vs
npm i dep --save
We have a build error and learned can bypass it by pasting. I know it isn't kosher but I really want to know why and what consequences that causes?
npm install dep doesn't add the dependency to the package.json file.
You have to add --save or --save-dev to add it to the package.json file.
Besides that, npm install will always serve you the latest build (in most cases the version tagged as latest (see npm docs)), unless you specify a specific version.
If you want your lock file to update, you have to delete the file before running npm install to generate a lock file with the dependency included (for more info check out this GitHub issue)
In conclussion it shouldn't make much of a difference if you manually add the dependency to package.json file and install it with npm install, unless the latest version of your dependency is broken.

npm - Semver versioning - Updating a package with a caret "^"

I have a npm package in my package.json file
"clean-webpack-plugin": "^0.1.18"
Now when I hover over the package I can see that there is a newer version
"clean-webpack-plugin": "^0.1.19"
Now, as I understood, I could for example do npm update to update all packages obeying the semver rules or just the package npm update clean-webpack-plugin.
So the caret ^ symbol should mean, that you could possibly update the packge to version 0.9.9 if available, right?
npm update has no effect, that's why I ask.
I'm quite certain that npm will have updated the application files for clean-webpack-plugin from version 0.1.18 to version 0.1.19 after you run: npm update clean-webpack-plugin as described in your question.
However, npm will not have updated the entry in your package.json as theoretically it's not actually necessary to do so. Why?.. because version "^0.1.18" is specified in package.json. I.e. The version is specified with the caret ^ symbol.
Let's say your were to publish your project with ^0.1.18 specified in package.json then any subsequent user running npm install will actually get version 0.1.19 anyway (caveat: as the version history for clean-webpack-plugin currently stands in the npm repository at the time of writing this).
So, in short I'm quite sure that version 0.1.19 has been installed on your system, it simply hasn't changed the version specified in package.json. It's not actually necessary to do so and the rules of semver and the use of the caret symbol are still being respected.
So the caret ^ symbol should mean, that you could possibly update the package to version 0.9.9 if available, right?
The caret in "^0.1.18" is saying to npm I WILL accept any updates to the most recent MINOR version but I WILL NOT accept a MAJOR update. I.e. ^0.1.18 means any updates in the range >=0.1.18 <1.0.0 (PATCH updates within that range are allowed too).
Verifying whether it has been updated:
To verify whether version 0.1.19 has actually been installed you can cd to your project directory and run:
npm ls clean-webpack-plugin
You should see the following logged to your console:
...
└── clean-webpack-plugin#0.1.19
But I want package.json to show "^0.1.19" after running npm update:
When you initially run npm update clean-webpack-plugin you could have:
Appended the --save-dev argument (applicable if it was listed in your devDependencies section of package.json).
Or, appended the --save argument (applicable if it was listed in your dependencies section of package.json).
Appending either --save-dev or --save as appropriate to npm update clean-webpack-plugin would have update the entry in package.json. This is further explained in the Recording Updates with --save section of the npm documentation.
By doing this, you can think of it as re-specifying the initial >= part of the range of updates you'll accept.
Note
Running npm update clean-webpack-plugin with the additional --save or --save-dev argument will not have any affect if npm ls clean-webpack-plugin reports:
...
└── clean-webpack-plugin#0.1.19
There would be nothing to update, so I'd just manually specify "^0.1.19" in package.json.

Tags may not have any characters that encodeURIComponent encodes

I'm migrating from bower to yarn, and in my bower.json file I have this dependency:
Snap.svg": "snap.svg#^0.4.1
When I tried to do the same in the yarn dependencies file, I got this error :
npm ERR! code EINVALIDTAGNAME
npm ERR! Invalid tag name "snap.svg#^0.4.1": Tags may not have any characters that encodeURIComponent encodes.
How can I solve this ?
Two things:
First, the npm package name -- which yarn uses since it uses package.json -- is snapsvg whereas snap.svg (with a dot) is only used for Bower. See the snapsvg npm page. The error you see is in reference to that dot in the package name.
Second, when I test installed it with yarn 1.2.1, I noticed that it complained that 0.4.1 was not available:
Couldn't find any versions for "snapsvg" that matches "^0.4.1"
? Please choose a version of "snapsvg" from this list: (Use arrow keys)
> 0.5.1
0.5.0
0.4.0
0.3.0
0.1.0
The resulting package.json entry should look like:
"dependencies": {
"snapsvg": "^0.4.0"
}
and yarn.lock:
snapsvg#^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/snapsvg/-/snapsvg-0.4.0.tgz#e0767014167825957de7e125c29b0fa89796ea03"
dependencies:
eve "~0.4.2"
Generally, when something weird like this happens, use yarn add with the package name manually and see what it does.
I was able to fix it by simply using below command
npm i --legacy-peer-deps

NPM - Deprecate check in Package.json

Is there a way to directly check a package.jsob for deprecated dependencies instead of finding it out during npm install? I.e. Just check and dont install.
Thanks
There is a way to make some pre-npm-install checking with npm-check utility. Install it globally and it will give you some information like
$ npm-check
webpack 😟 MISSING! Not installed.
😎 MAJOR UP Major update available. https://github.com/webpack/webpack
npm install --save-dev webpack#3.5.6 to go from 2.7.0 to 3.5.6
Also you may try npm-check-updates utility. I guess it's more useful (and it works faster). It gives an information not only for major versions:
$ ncu -l verbose --packageFile package.json
webpack ^2.6.1 → ^3.5.6
express ^4.14.0 → ^4.15.4
I was able to use the second utility only with --packageFile option.
As you can see, it does not deal with npm deprecation explicitly, but may help in case you don't want to make npm install.