How to remove optional peer dependency from NPM project? - npm

I am participating in building a webapp that used to use node-sass. We migrated to sass in the meantime but we have still node-sass in our package-lock.json. I want to fix that.
In the beginning, we had something like this
$ npm ls node-sass
cookbook#0.9.13 /home/private/Documents/Projekte/nextcloud-apps/nextcloud-app-dev/volumes/custom_apps/cookbook
├── node-sass#7.0.1
└─┬ sass-loader#13.0.2
└── node-sass#7.0.1 deduped
OK, lets remove the dependency by calling npm uninstall node-sass. The result is
$ npm ls node-sass
cookbook#0.9.13 /home/private/Documents/Projekte/nextcloud-apps/nextcloud-app-dev/volumes/custom_apps/cookbook
└─┬ sass-loader#13.0.2
└── node-sass#7.0.1
I do not get the reason, why sass-loader is still depending on node-sass. OK, let's have a closer look:
$ npm why node-sass
node-sass#7.0.1 optional peer
node_modules/node-sass
peerOptional node-sass#"^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" from sass-loader#13.0.2
node_modules/sass-loader
sass-loader#"^13.0.2" from the root project
peer sass-loader#"^13.0.1" from #nextcloud/webpack-vue-config#5.3.0
node_modules/#nextcloud/webpack-vue-config
dev #nextcloud/webpack-vue-config#"^5.0.0" from the root project
Now I am a bit surprised. The package node-sass is only installed as a peer dependency. So, why is it installed at all? I thought the idea of peer dependencies is to allow for the root project to select the version in use.
Also, it is only optional. So, it should be able to remove it (eventually there might be a warning during removal but nothing serious).
I am not working on the #nextcloud/webpack-vue-config package. It is a mere dev dependency of the webapp. So, NPM should not install the node-sass as a dev dependency on any of my dependencies.
How can I remove the node-sass package from my project's package-lock.json? It is still anchored in the package-lock.json and thus installed on each build.
I could use the --no-optional CLI option of npm to skip over all optional dependencies. I do not want to do that. The "problem" with this is that the GitHub dependency checker will not consider the node-sass module as skipped and continue complaining. Also, other optional dependencies might be skipped as well, although we would like to have them.

I ran into this with node-sass and sass-loader the other day.
Easy solve for me was to remove #nextcloud/webpack-vue-config from my package.json, do an npm install then put it back and rerun npm install
that was enough to get the internals reset to make node-sass go away.

Related

How to change the installed version of a nested global npm package?

For one of the globally installed npm packages I use, one of the dependencies received a minor version upgrade that unfortunately introduces breaking changes. In the below output, amplify-codegen version 2.28.1 was installed. When executing the command previously, amplify-codegen 2.28.0 would be installed.
npm i -g #aws-amplify/cli#6.4.0
npm list -g amplify-codegen
└─┬ #aws-amplify/cli#6.4.0
├── amplify-codegen#2.28.1
├─┬ amplify-provider-awscloudformation#4.65.0
│ └── amplify-codegen#2.28.1 deduped
Here the problem is that, despite the update from 2.28.0 to 2.28.1 being a minor version update, it introduces changes that break our project. So we would like to revert the update, and ensure that when installing #aws-amplify/cli#6.4.0, the 2.28.0 version of amplify-codegen is installed.
For a locally installed package, this could be easily resolved with a yarn.lock or the "overrides" option in the package.json. However, for globally installed packages, I'm struggling to find a solution, as there's no equivalent of a yarn.lock or package.json for globally installed npm packages.

How do I force npm to reinstall a single package, even if the version number is the same?

In my Node.js project, I have a dependency on another local project. Oftentimes, I need to make a small change to the dependency and see how it affects my main project. In order to do this, I have to reinstall my dependency using npm.
I can use npm update to try to update my dependency, but this seems like it will only work if the version number has changed on the dependency. I don't want to have to change the version number on my dependency every time I change a line of code or two to make an experimental change in development.
I can rm -rf node_modules/; npm install to ensure that I get the latest versions of all of my dependencies. Downloading all of my non-local dependencies takes several minutes, breaking up my train of thought.
Is there a way to force npm to reinstall a single dependency, even if that dependency's version number hasn't changed?
When you run npm install, it will install any missing dependencies, so you can combine it with an uninstall like this:
npm uninstall some_module; npm install
With npm 5, uninstalled modules are removed from the package.json, so you should use:
npm uninstall some_module; npm install some_module
On npm v 6.14:
npm install module_name --force --no-save
You get a message stating:
npm WARN using --force I sure hope you know what you are doing.
And then it proceeds to uninstall and reinstall the package.
Note: if you don't specify the --no-save option, npm updates the package version on package.json to the highest version that is compatible with the existing SemVer rule.
If you do not want npm to update the package's version on package.json, keep the --no-save option.
Not the best answer, but just for information, you can run
npm ci
It is the same as npm install, but it will remove the existing node_modules folder, if any, and do a fresh install for all packages. This is useful if the files in node_modules have been changed for some reason and you want to revert them to their original state.

npm: using 'npm uninstall' vs. just removing the folder

I wanted to try grunt-babel, so I opened up a terminal in my Home folder and did npm install --save-dev grunt-babel babel-preset-es2015 according to the plugin's instructions.
I was doing this too hastily, and realized I should probably have done this in my new project folder where I am dabbling with ES6 code. I had not even done npm init in that folder nor in the Home folder from where I executed the install command.
When I do npm uninstall grunt-babel, the preset files are removed but 91 folders of different dependencies remain in the node_modules folder.
Can I simply remove the folder instead of running npm uninstall 91 times?
This guy asked a similar question but none of the answers address his subquestion of just removing the folder: how to uninstall npm modules in node js?
npm uninstall <name> removes the module from node_modules, but not package.json.
npm uninstall <name> --save to also delete the dependency from package.json.
npm rm <package_name> removes the packages when uninstall not working
npm prune <name> (see docs) for extraneous packages and packages that are not listed on the parent package's dependencies list.
If you don't want to uninstall one by one run
rm -rf node_modules && npm cache clean && npm install
It's a good way for being sure the packages you uninstall are no more in the packages json.
Now in 2021 npm uninstall <name> will also removed it from package.json
UPDATED answer (2020):
These are all aliases to uninstall:
remove, rm, r, un, unlink
And today there is no need for --save flag since it is the default. The same goes for install BTW.
Use npm list as a tool to understand your changes. I usually use the time to make a capture file like:
npm list >1307
do some change
npm list >1309
so then:
cat 13??
or an editor lets me see what npm thinks it did.
For uninstall, only packages on the root all size of 'whole package' get removed. Other then that, the command is politely ignored...
For example:
├── safe-stable-stringify#1.1.0
├── semver#6.3.0
├─┬ tableify#1.1.0
│ └─┬ optimist#0.6.1
│ ├── minimist#0.0.8 deduped
│ └── wordwrap#0.0.3
safe-stable-stringify is a removal candidate, but wordwrap is not. Think about it, this is entirely reasonable !
npm uninstall pkgtoyank -save
updates packages.json by removing it from there as well.
npm is very well designed to say the least. I usually hugely avoid directly poking under it in ./node_modules I will copy things out from there to look at them, but why yank on a leash of a BIG CAT and get bit. it works; use it as its intended....

What does ` UNMET PEER DEPENDENCY <packageName> extraneous` mean?

I understand that UNMET PEER DEPENDENCY means I need to npm install one of my peerDependencies. I believe that extraneous means the package exists but is not listed in package.json (presumably because it's installed globally?).
What does it mean to have the two of them together?
And why am I seeing this error even though I see these packages in node_modules, at the correct versions?
It means that you have a module installed in your local npm repo that is "extraneous" (meaning you have no dependency on it) that has an "unmet peer dependency" on a library you also do not have installed (or if you do have it installed locally or globally, it is also extraneous so it's not in your dependency tree). If you run npm prune it should remove the extraneous dependency and this message.

Peer dependency errors from npm even though actual dependency version correctly follows semver

I'm getting npm ERR! invalid errors when I try npm ls or npm install, and it seems like npm is incorrectly thinking peers have incompatible versions. A good example (I get several of these at a time):
npm WARN unmet dependency /MYLOCALPROJECTDIRECTORY/node_modules/grunt-contrib-imagemin/node_modules/imagemin/node_modules/imagemin-gifsicle requires image-type#'^0.1.1' but will load
npm WARN unmet dependency /MYLOCALPROJECTDIRECTORY/node_modules/grunt-contrib-imagemin/node_modules/imagemin/node_modules/image-type,
npm WARN unmet dependency which is version 0.1.4
According to the rules of semver, the caret "^" operator should match a requirement of ^0.1.1 with an actual dependency of version 0.1.4 just fine.
I've installed Node v0.10.30 with npm v1.4.23 using Homebrew (both the latest stables), running OS X Mountain Lion. I'd appreciate tips on finding how to reliably reproduce this - last time I totally uninstalled/reinstalled Node and npm, same local npm modules and everything, and could not find the error again. Came back to work the next day, tried to install some grunt plugin, and ran into all these errors again.
If you happen to reproduce it, I bet you can solve it by removing the node_modules folder, cleaning the cache and reinstalling:
rm -rf ./node_modules
npm cache clean
npm install
I know this is not an actual answer, but I guess it's better than uninstalling/reinstalling node/npm.