npm install only if package missing or out-of-date compared to package.json - npm

I want to be able to compare my locally installed packages against my project package.json file without making a call against the npm online repo. If there is a package that is out of date based on the package.json file, then and only then will it go to the npm online repo and install the package.
The reason for this is that I want to be able to update the package.json file to require a newer version of a package, commit this change to the project repo and when other developers on the team get latest their npm package is updated. I do not want to slow down the process if everything is up-to-date or cause the build to fail if access to the npm repo or the internet is down.
I am wondering if this is an already solved use-case or do I need to parse the package.json file and compare it to a "npm ls" output myself?

you will need to setup a local repository (by duplicating the NPM couchdb localy)
( see https://stackoverflow.com/a/7577265/406458)
then you could use npm-check-updates.
npm-check-updates will give you a list of packages that can be updated in your package.json file see
https://www.npmjs.org/package/npm-check-updates
$ npm-check-updates
"connect" can be updated from 2.8.x to 2.11.x (Installed: 2.8.8,
Latest: 2.11.0) "commander" can be updated from 1.3.x to 2.0.x
(Installed: 1.3.2, Latest: 2.0.0)
Run 'npm-check-updates -u' to upgrade your package.json automatically
Check global npm packages for updates:
$ npm-check-updates -u

Related

Is there a way to install an npm package locally but not affect package.json or package-lock.json?

I have a project that I'm working on for a client where I have two private packages (which I can't get access to npm install) are inside the package.json.
I do however have access to clone the repos for those said packages. If I simply run an npm install I'll get a permission denied error. Same if I run npm link to the packages.
I've been working around this by removing the packages from the package.json then running npm install ../some-package. This works but isn't a great solution because if I wanted to add a new package I'd have to deal with a bit of a mess with the package.json.
Is there a better way than this?
I have tried running npm link ../some-package but I still get access denied. The only way I've managed to complete an install is by removing the packages then installing them from a local dir.
I don't know the details of your situation, but I see at least two potential solutions to explore.
Option 1: Install the package from the repo
I do however have access to clone the repos for those said packages.
You can install from a git repo and package.json will record that git repo as the source of the package rather than the npm registry.
From the docs at https://docs.npmjs.com/cli/v8/commands/npm-install:
npm install :
Installs the package from the hosted git provider, cloning it with git. For a full git remote url, only that URL will be attempted.
Option 2: Install from the local file system with --no-save
If that approach doesn't work for you, you can try npm install --no-save ../some-package as a build step. The --no-save makes it so it doesn't modify package.json.

How to update npm package's dependency?

I am trying to update dependency of package I am installing trough npm.
When I install appium package, I get version 1.22.0 which is correct. But this package also have dependencies that getting regular updates on github and are propagated on npmjs.
But when I install main package, dependency is not latest.
For example, I need to update appium-espresso-driver dependency of appium to 1.50.1, but everytime I install appium, dependency is only 1.45.3, even when appium have ^1.0.0 in package.json
How to update this? Do I need to wait for appium package to be bumped?
If you want to update all the packages to the latest version and you are using npm, you can see this documentation npm-update, but the short answer is:
npm update
This helps to update every package of the project, you can do it in the root folder, and update everything in the package.json.
If you want to update everything to a latest version, you can use npm-check-updates, this will check the latest version of the packages that you have installed on package.json, I will show you the easy steps to install this but you can go through the documentation of the module in here:
npm install -g npm-check-updates
This will install you the package, then after that you need to run in in the root folder:
ncu -u
So after that command it will update all the packages in the package.json but not install them, so after running ncu -u you need to run again:
npm install
To install the new versions of the package.

What is the difference between "npm install" and "npm ci"?

I'm working with continuous integration and discovered the npm ci command.
I can't figure what the advantages are of using this command for my workflow.
Is it faster? Does it make the test harder, okay, and after?
From the official documentation for npm ci:
In short, the main differences between using npm install and npm ci are:
The project must have an existing package-lock.json or npm-shrinkwrap.json.
If dependencies in the package lock do not match those in package.json, npm ci will exit with an error, instead of updating the package lock.
npm ci can only install entire projects at a time: individual dependencies cannot be added with this command.
If a node_modules is already present, it will be automatically removed before npm ci begins its install.
It will never write to package.json or any of the package-locks: installs are essentially frozen.
Essentially,
npm install reads package.json to create a list of dependencies and uses package-lock.json to inform which versions of these dependencies to install. If a dependency is not in package-lock.json it will be added by npm install.
npm ci (also known as Clean Install) is meant to be used in automated environments — such as test platforms, continuous integration, and deployment — or, any situation where you want to make sure you're doing a clean install of your dependencies.
It installs dependencies directly from package-lock.json and uses package.json only to validate that there are no mismatched versions. If any dependencies are missing or have incompatible versions, it will throw an error.
Use npm install to add new dependencies, and to update dependencies on a project. Usually, you would use it during development after pulling changes that update the list of dependencies but it may be a good idea to use npm ci in this case.
Use npm ci if you need a deterministic, repeatable build. For example during continuous integration, automated jobs, etc. and when installing dependencies for the first time, instead of npm install.
npm install
Installs a package and all its dependencies.
Dependencies are driven by npm-shrinkwrap.json and package-lock.json (in that order).
without arguments: installs dependencies of a local module.
Can install global packages.
Will install any missing dependencies in node_modules.
It may write to package.json or package-lock.json.
When used with an argument (npm i packagename) it may write to package.json to add or update the dependency.
when used without arguments, (npm i) it may write to package-lock.json to lock down the version of some dependencies if they are not already in this file.
npm ci
Requires at least npm v5.7.1.
Requires package-lock.json or npm-shrinkwrap.json to be present.
Throws an error if dependencies from these two files don't match package.json.
Removes node_modules and install all dependencies at once.
It never writes to package.json or package-lock.json.
Algorithm
While npm ci generates the entire dependency tree from package-lock.json or npm-shrinkwrap.json, npm install updates the contents of node_modules using the following algorithm (source):
load the existing node_modules tree from disk
clone the tree
fetch the package.json and assorted metadata and add it to the clone
walk the clone and add any missing dependencies
dependencies will be added as close to the top as is possible
without breaking any other modules
compare the original tree with the cloned tree and make a list of
actions to take to convert one to the other
execute all of the actions, deepest first
kinds of actions are install, update, remove and move
npm ci will delete any existing node_modules folder and relies on the package-lock.json file to install the specific version of each package. It is significantly faster than npm install because it skips some features. Its clean state install is great for ci/cd pipelines and docker builds! You also use it to install everything all at once and not specific packages.
While everyone else has answered the technical differences none explain in what situations to use both.
You should use them in different situations.
npm install is great for development and in the CI when you want to cache the node_modules directory.
When to use this? You can do this if you are making a package for other people to use (you do NOT include node_modules in such a release). Regarding the caching, be careful, if you plan to support different versions of Node.js remember that node_modules might have to be reinstalled due to differences between the Node.js runtime requirements. If you wish to stick to one version, stick to the latest LTS.
npm ci should be used when you are to test and release a production application (a final product, not to be used by other packages) since it is important that you have the installation be as deterministic as possible, this install will take longer but will ultimately make your application more reliable (you do include node_modules in such a release). Stick with LTS version of Node.js.
npm i and npm ci both utilize the npm cache if it exists, this cache lives normally at ~/.npm.
Also, npm ci respects the package-lock.json file. Unlike npm install, which rewrites the file and always installs new versions.
Bonus: You could mix them depending on how complex you want to make it. On feature branches in git you could cache the node_modules to increase your teams productivity and on the merge request and master branches rely on npm ci for a deterministic outcome.
The documentation you linked had the summary:
In short, the main differences between using npm install and npm ci are:
The project must have an existing package-lock.json or npm-shrinkwrap.json.
If dependencies in the package lock do not match those in package.json, npm ci will exit with an error, instead of updating the package lock.
npm ci can only install entire projects at a time: individual dependencies cannot be added with this command.
If a node_modules is already present, it will be automatically removed before npm ci begins its install.
It will never write to package.json or any of the package-locks: installs are essentially frozen.
The commands are very similar in functionality however the difference is in the approach taken to install the dependencies specified in your package.json and package-lock.json files.
npm ci performs a clean install of all the dependencies of your app whereas npm install may skip some installations if they already exist on the system. A problem may arise if the version already installed on the system isn't the one your package.json intended to install i.e. the installed version is different from the 'required' version.
Other differences would be that npm ci never touches your package*.json files. It will stop installation and show an error if the dependency versions do not match in the package.json and package-lock.json files.
You can read a much better explanation from the official docs here.
Additionally, you may want to read about package locks here.
It is worth having in mind that light node docker images like alpine do not have Python installed which is a dependency of node-gyp which is used by npm ci.
I think it's a bit opinionated that in order to have npm ci working you need to install Python as dependency in your build.
More info here Docker and npm - gyp ERR! not ok
npm ci - install exactly what is listed in package-lock.json
npm install - without changing any versions in package.json, use package.json to create/update package-lock.json, then install exactly what is listed in package-lock.json
npm update - update package.json packages to latest versions, then use package.json to create/update package-lock.json, then install exactly what is listed in package-lock.json
Or said a different way, npm ci changes 0 package files, npm install changes 1 package file, and npm update changes 2 package files.
It does a clean install, use it in situations where you would delete node_modules and re-run npm i.
I have no idea why some people think it's short for "continuous integration". There is an npm install command that can be run as npm i and an npm clean-install command that can be run as npm ci.
npm install is the command used to install the dependencies listed in a project's package.json file, while npm ci is a command that installs dependencies from a package-lock.json or npm-shrinkwrap.json file. The npm ci command is typically used in continuous integration (CI) environments, where the package-lock.json or npm-shrinkwrap.json file is checked into version control and should not be modified. Because npm ci installs dependencies from a locked file, it is a faster and more reliable way to install dependencies than npm install, which could install different versions of dependencies based on the state of the package.json file.

Can I re-create node_modules from package-lock.json?

I cloned a repository from github which has a package-lock.json (but no package.json). Then in a git bash terminal I go to the directory and run npm install but I just get a message saying there is no package.json and then everything in package-lock.json gets deleted so it's basically empty except for the project name and version.
I thought running npm install with a package-lock.json in the directory was enough to re-create node_modules, but am I seriously misunderstanding how this works? By the way I have node 8.12.0 and npm 6.4.1 and am running on Windows 10. Also, I think the package-lock.json was created on a unix system so could there be problems when using package-lock.json on a different OS?
I already tried running npm init just to get a package.json file and then running npm install but that still didn't get me a node_modules folder.
Starting from Mar 5, 2018, you can run npm ci to install packages from package-lock.json.
npm ci bypasses a package’s package.json to install modules from a
package’s lockfile.
https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable
package-lock.json records the exact version and url of packages need to install, thus you can use npm to install them accordingly:
npm can install from urls that point to tarballs
--no-package-lock option to tell npm to not touch package-lock.json file
For example, to install all packages in package-lock.json:
cat package-lock.json | jq '.dependencies[].resolved' | xargs npm i --no-package-lock
jq is a command line tool to pares jq, you can write a simple JavaScript script to parse it instead (if you do not want to install jq or learn jq's query syntax).
AFAIK, the package-lock.json file relies on the presence of a package.json file, so you'll not be able to recreate your node_modules folder from the package-lock.json file alone (happy to be proved wrong here).
Therefore, your best bet is to (mis)use a module like auto-install that is capable of generating the package.json file based on a project's dependencies, as they appear in the files.
Install it globally (npm install -g auto-install), then you'll need to generate an empty package.json file for it to run (use npm init -y in your project root). Kick things off with the command auto-install and it should add the dependencies to the package.json file.
HTH

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.