npm5 package-lock.json different entries on different machines - npm

Our project uses npm for package management. After upgrading from npm 4 to npm 5, we decided to opt-in for the new package-lock.json.
After committing it and performing npm install on other machines, we spotted differences in the way the version and resolved entries are specified:
1) example of package-lock.json dependencies with version encoded as URL:
"jspm": {
"version": "https://registry.npmjs.org/jspm/-/jspm-0.16.52.tgz",
"integrity": "sha1-axhH4I8TGsm9JnzFiXSXmudnXS4=",
"dev": true
},
"systemjs": {
"version": "https://registry.npmjs.org/systemjs/-/systemjs-0.19.46.tgz",
"integrity": "sha1-wEV0szNfBSoOPHoA7kGIxuTB444=",
"dev": true
},
2) example of package-lock.json dependencies with version and resolved properties:
"jspm": {
"version": "0.16.53",
"resolved": "https://registry.npmjs.org/jspm/-/jspm-0.16.53.tgz",
"integrity": "sha1-VvNR9JWUyJM+XgG2UUWsrr/PtZ4=",
"dev": true,
"dependencies": {
...
}
},
"systemjs": {
"version": "0.19.46",
"resolved": "https://registry.npmjs.org/systemjs/-/systemjs-0.19.46.tgz",
"integrity": "sha1-wEV0szNfBSoOPHoA7kGIxuTB444=",
"dev": true
},
...
In addition to having an unstable package-lock.json, our build server is having issues when installing the first example.

Follow this procedure to produce a stable version of the package-lock.json:
delete the existing node_modules folder
delete the existing package-lock.json
perform npm install
commit and push the package-lock.json
For the rest of the team:
delete the existing node_modules folder
pull the new package-lock.json
perform npm install
Deleting the existing node_modules before continuing is an essential step because the package-lock.json does parse existing metadata from the node_modules folder.
This means that if your node_modules folder has leftovers, they may get added to the package-lock's dependencies, even if they're not an actual dependency (anymore).

You may want to check in this situation on both machines that:
your node + npm version are the same and maybe doing npm -g update npm.
the npm configuration property save-exact has the same value on both machines. (otherwise doing npm config set save_exact true/false)

Related

Why does jsonlines package get resolved to registry.npm.taobao.org?

When I install the npm package jsonlines, it gets resolved to a mirrored registry registry.npm.taobao.org rather than registry.npmjs.org. It only does this for jsonlines. What causes this?
Here's the diff on my package-lock.json. The original "resolved" value was created when another developer installed the package:
"jsonlines": {
"version": "0.1.1",
- "resolved": "https://registry.npmjs.org/jsonlines/-/jsonlines-0.1.1.tgz",
+ "resolved": "https://registry.npm.taobao.org/jsonlines/download/jsonlines-0.1.1.tgz",
"integrity": "sha1-T80kbcXQ44aRkHxEqwAveC0dlMw="
},
I confirmed my configured registry is npmjs.org:
$ npm config get registry
https://registry.npmjs.org/
The developer's npm registry was likely set to registry.npm.taobao.org when they ran npm install jsonlines. Some users have npm configured to use the taobao registry for geographic proximity.
Deleting node_modules and package-lock.json and re-running npm install fixes it.
Tip: Use lockfile-lint to prevent it from happening again.
npm install --save-dev lockfile-lint
Run lockfile-lint to your lint script, ideally in a pre-push git hook.
Add this config to your package.json:
"lockfile-lint": {
"allowed-schemes": [
"https:"
],
"allowed-hosts": [
"npm"
],
"empty-hostname": false,
"type": "npm ",
"path": "package-lock.json"
},

Can "NPM -i" (local) install a global package without i know it?

I'm ok with local dependencies that packages install. But now I have a huge concerns about if a local installed package can install other global packages as dependencies.
as example:
npm install nunjucks
npm install sqlite
or
npm install botkit
It is not possible to mark a dependency as global in package.json, so that it is installed system-wide when you run npm i.
Here's an old comment by Isaac Schlueter stating that this will never be implemented.
Hooowever, it would be really simple to write a preinstall script to install arbitary dependencies globally.
{
"name": "Project",
"version": "1.0.0",
"description": "Preinstall script to install global deps",
"main": "index.js",
"scripts": {
"preinstall": "node -e \"const {execSync} = require('child_process'); JSON.parse(fs.readFileSync('package.json')).globalDependencies.forEach(globalDep => execSync('npm i -g ' + globalDep));\""
},
"dependencies": {
"react": "16.13.1"
},
"globalDependencies": [
"lodash"
],
"license": "ISC"
}
Copy this code into a package.json file in a folder on your PC. Then, in the folder run npm i. It will install React locally (in a node_modules folder) and it will install lodash globally.
You can verify this using: npm i ls -g --depth=0.
Reference: Install dependencies globally and locally using package.json
As to your question:
Can npm -i (local) install a global package without me knowing it?
It's not entirely silent. When running npm i for the above package.json file, you would see the following output:
> Project#1.0.0 preinstall /home/jim/Desktop/Project
> node -e "const {execSync} = require('child_process'); JSON.parse(fs.readFileSync('package.json')).globalDependencies.forEach(globalDep => execSync('npm i -g ' + globalDep));"
npm WARN Project#1.0.0 No repository field.
audited 6 packages in 1.113s
found 0 vulnerabilities
But whether you would catch this when running npm i on a large project is debatable.

Why is npm installing packages from private registry and not from registry.npmjs.org

I have create a .nmprc file in my project directory as:
#mycompany:registry=https://registry.mycompany.com/
However when I do npm install I see package dependencies which do not start with #mycompany also gets installed from https://registry.mycompany.com/ and not from https://registry.npmjs.org/.
This is what I see in package-lock.json:
"yaml": {
"version": "1.7.2",
"resolved": "https://registry.mycompany.com/yaml/-/yaml-1.7.2.tgz",
"integrity": "sha512-qXROVp90sb83XtAoqE8bP9RwAkTTZbugRUTm5YeFCBfNRPEp2YzTeqWiz7m5OORHzEvrA/qcGS8hp/E+MMROYw==",
"dev": true,
"requires": {
"#babel/runtime": "^7.6.3"
}
Since you're using an .npmrc File, the command npm install will try to find all packages in your companies registry https://registry.mycompany.com/
If you want to install all the other Packages you need to update your .npmrc File as followed.
Your Current .npmrc File:
#mycompany:registry=https://registry.mycompany.com/
Updated Version
#mycompany:registry=https://registry.mycompany.com/
registry=https://registry.npmjs.org
If you run npm install it will install all Packages with the #mycompany FLag from your companies Registry and it will try to install all other packages from the public npm Registry.

package-lock.json resolved link points to local artifactory URL instead of globally set registry

I have a .npmrc file with:
registy=http://artifacts.sample.com/artifactory/api/npm/
package-lock.json contains resolved field for dependencies which looks something like:
"dependencies": {
"acorn": {
"version": "5.7.3",
"resolved": "http://artifacts.sample.com/artifactory/api/npm/acorn/-/acorn-5.7.3.tgz",
"integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==",
"dev": true
}
Now, when I do npm install, it changes the package-lock.json resolved field to point to a local artifactory instead of the one specified in .npmrc like:
"dependencies": {
"acorn": {
"version": "5.7.3",
"resolved": "http://localrepo.sample.com/artifactory/api/npm/acorn/-/acorn-5.7.3.tgz",
"integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==",
"dev": true
}
We have localized code and this will give access denied to someone living on the other side of the world, where their artifacts URL points somewhere else, or it will just change the package-lock.json file for them to point to their local URL instead, and we will always have changing package-lock.json file.
I had issues with "dev" and "integrity" too, but they were fixed using https://github.com/npm/npm/issues/16938#issuecomment-339863980
I'm on the latest versions of node and npm.
node -v
v10.15.3
npm -v
6.9.0
Is there anyway we can avoid this?
From my own experience. If you have setup default registry, the "resolved" field in package-lock.json will have no effect. I just followed Artifactory npm registry official doc.
npm config set registry https://artifactory.my.com/artifactory/api/npm/npm-repo/
npm login
npm config set //artifactory.my.com/artifactory/api/npm/npm-repo/:always-auth=true
Alternatively, a simple trick is to update the host file (eg. /etc/hosts) to ensure the "resolved" field url is never reachable, this will help you to observe npm behaviour.

npm install removes "dev": true from several packages in package-lock.json?

Today I pulled latest from a shared Git repository and noticed that another developer on my team added an NPM package. So I ran npm install, and then saw that my package-lock.json file had changed. When I dug into what had changed, I found that "dev": true had been removed from several package descriptions, for example:
"some-package": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/whatever/-/some-package-1.0.0.tgz",
"integrity": "some-big-hash",
"dev": true
},
The "dev": true is gone after npm install from several packages. Should I be concerned that NPM did this? I don't want these packages to be installed for production.
This question about "dev": true is somewhat related, but there isn't a good answer yet and I still want to know if I'm doing something wrong. Why is NPM removing this?
Your "dev": true disappeared because the package became a non-dev dependency.
A package with "dev": true is only needed in development, not in production.
This means it is required, directly or indirectly, only via devDependencies and not via anything in dependencies.
It will not be installed if you do npm install --production or have NODE_ENV=production in the environment.