for example, when I need to install webpack, usually we are supposed to use "npm i -D webpack", but if I use "npm i webpack" instead, there is no difference in my final bundle file, why we need to specify '-D'?
I think there is no differences between them, why not just use npm i?
npm i -D
npm i
As per the docs, npm install -D means you are installing the package as a devDependency and not a regular dependency.
How is this different?
When your app is deployed and your server runs the npm install step, it will only install the packages that are in dependency and not those in devDependency. Hence, we usually install things like eslint, typescript and such as devDependency and not regular depedency.
Reference
https://docs.npmjs.com/cli/v6/commands/npm-install
Related
I'm using npm as part of me building the production docker image.
I want to make sure the package-lock.json doesn't change and matches.
You can use npm ci.
npm ci bypasses a package’s package.json to install modules from a package’s lockfile. This ensures reproducible builds—you are getting exactly what you expect on every install.
https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable
How I can skip installing optional dependencies from package-lock.json by npm ci?
You can use npm ci --no-optional .
If npm still installs the optional package. Then try after removing package.lock.json and run the command again.
There was an error in NPM's implementation of npm ci --no-optional. It has been fixed in versions > 6.13.3 - maybe earlier versions as well, but I can only vouch for 6.13.4 and up.
I was facing this issue with CI workflow script and even "--no-optional" was not working
npm ci --no-optional
The above command only worked when I added the optional package as
"optionalDependencies": {
"fsevents": "^2.3.2"
}
in the package.json file
It's not a proper solution, rather an ugly one, but it helped me out. It looks like npm ci --no-optional doesn't work and probably never worked. But at the same time flag --production works. And if we afford mutating package.json (e.g. in a docker container) then...
So I wrote a simple script that:
reads package.json content
Object.assign(cfg.dependencies, cfg.devDependencies)
delete cfg.devDependencies
overwrites the initial package.json
So finally we have:
dependencies contains both normal & dev dependencies
devDependencies section is empty
optionalDependencies are intact
And when we run npm ci --production we got what we want - no optional dependencies (in my case cypress). Due to the fact that all these steps are performed inside of a docker container we can mutate package.json.
But I'm not sure that it'll help you too.
In order to make npm ci --no-optional skip/ignore an optional pacakge, it's important to understand how npm intracts with package.json and pacakge-lock.json.
npm install --no-optional (is only effective if pacakge-lock.json doesn't exists otherwise it would ignore --no-optional)*
npm ci --no-optional is only effective if pakcage-lock.json was already created with npm install --no-optional**.
* This means if you want to make an already installed package an optional, you can would have to
Add it "optionalDependencies": either manulally or through npm install pacakge-name --save-optional
Delete the pacakge-lock.json.
then run rm -rf node_modules/
Lastly run npm install --no-optional
Add this point npm ci --no-optional isn't suppose to install it.
** TIP: you could debug if a certian package is assigned as optional by running npm ls package-name
Note: This one the reason why its recommended to keep trak pacakge-lock.json with git repo of the project.
I'm building my CI on gitlab and one of the jobs I need to execute is to compile sass stylesheets.
In order to compile sass I'm using node-sass which when installed needs to be compiled from source.
In order NOT to compile every time node-sass from source, I created a docker image with:
node and npm
node-sass installed globally (npm install --unsafe-perm -g node-sass)
In my project's package.json I kept node-sass devDependencies with the very same version of the one installed in the docker image described above.
My problem is that when I execute npm install (right before compiling my scss), npm tries to install node-sass again and goes through the whole compilation from source process.
How can avoid this?
One solution I thought, is to remove node-sass from the devDependencies and just add them as optionalDependencies or something, but I don't like this dirty solution.
Does anyone even know why npm tries to install node-sass anyway even though the version requested by package.json it is globally installed?
I solved by adding node-sass to package.json as optional dependency like so:
"optionalDependencies": {
"node-sass": "4.10.0"
},
and now, whenever I need to skip the installation because I know there is a global version installed, I just do:
npm install --no-optional
This is kind of a work around nut it works great.
Working on a project where I need to install npm packages from several registries - the default npm registry and several custom registries.
My existing solution is to use npm scripts to break the install into steps which use the --registry flag. Something like this:
"install-pkg1": "npm install pkg1 --registry https://pkg1.domain.com",
"install-pkg2": "npm install pkg2 --registry https://pkg2.domain.com",
"install-custom": "npm install && npm run install-pkg1 && npm run install-pkg2"
Then use npm run install-custom in place of npm install to install all the dependencies.
Is there a more preferred method for installing packages from multiple registries?
As noted in the comments below, there is a discussion on Github about this.
This is pretty much one of the reasons for npm ci. The registries and versions will be defined there so you shouldnt need to do anything crazy to get them all from their corresponding registries. Also, this can kind of be accomplished with scopes, where you associate a registry with a scope, but this requires you publishing the packages scoped as whatever. more info on associating registry with scopes
I would like to list some modules that I want to install globally - they are not project related (things like bower, npm-check-updates, ... which I use all the time). Is it possible to manage this with a "global" package.json, or do I need to maintain a separate shell script to perform this installation? Currently I am doing:
# global-npm-pacakges.sh
npm install -g npm-check-updates#1.5.1
npm install -g bower#1.4.1
Any other way of doing this?
Your way is fine but that means you also need to maintain another script to
uninstall all of them globally
Using npm install -g with a global package.json, you still have to manage a clean up script.
There is no npm uninstall -g based on the package.json.
I think you need to
npm uninstall name<#version> or
npm -R name<#version>
Doing npm -R node_modules is not gracefully way of doing it.
It does not clean up the /tmp/xxx
There is some suggestions of using a symlink in this threads for your references:
How do I install a module globally using npm?