Joshua's Docs - NPM Cheatsheet and Assorted Notes
Light
help

👉 You might also be interested in my NodeJS notes, or notes on building an NPM package.

Upgrading NPM itself

  • Check version with npm -v
  • Upgrade depends on OS - full details

    • *nix - npm install -g npm@latest or npm install -g npm@next
    • Windows: Use this tool

      • npm install --global --production npm-windows-upgrade
      • npm-windows-upgrade --npm-version latest or npm-windows-upgrade
      • If any of the above fail:

        • Make sure you are in elevated prompt
        • Set-ExecutionPolicy Unrestricted -Scope CurrentUser -Force
        • If still failing, you might need to upgrade Node - [link]https://nodejs.org/en/download/)

Finding the NPM source directory

where npm

Init

npm init, or without the step-by-step questions, npm init -y

Some useful install flags - see full list here

Flag Full Flag Description
-g --global Save globally instead of into local project
NA --link Link globally installed packages into local project
-P --save-prod Save into dependencies section. Default
-D --save-dev Package will show in devDependencies
-O --save-optional Package will show in optionalDependencies
NA --no-save Does not save to package.json at all!

Viewing and Exploring the Contents of an NPM Package

Aside from installing locally and then manually exploring the files added to your computer under node_modules, you can also explore the contents of a published NPM package with some online tools:

  • UNPKG

    • Sample Options:

      • unpkg.com/:package@:version/:file (specific file)
      • unpkg.com/:package@:version/ (directory listing)
    • For example: unpkg.com/react/
  • runpkg

    • Similar options to UNPKG, and you should be able to just add r at the beginning of a unpkg URL to redirect
    • Example: runpkg.com/react/

Semver

Updating release versions

You can use npm version {semVerString} to set a new version. This will update package.json, package-lock.json, and npm-shrinkwrap.json.

A helpful thing to remember is that, without any other arguments, this does a lot of automatic stuff you might not want:

  • Adds a new git commit with automated message

    • Use custom with -m arg
  • Add a new git tag, and points it at the auto commit

    • Use --no-git-tag-version to disable
  • Updates the npm files (as mentioned above)
  • Runs preversion, version and postversion under scripts.

Update version without tagging OR adding commit

Use the --no-git-tag-version arg, or git-tag-version=false

Auto version bump

If you don't want to manually type out a version string, you can just auto bump the version, so long as you are using a valid semVer in your npm files. Use npm version {incrementTarget} where {incrementTarget} is one of:

  • major
  • minor
  • patch
  • premajor
  • preminor
  • prepatch
  • prerelease

Including the Lockfile

A common question devs have about projects that use a package manager is "should I commit the lockfile to version control?". In general, yes, especially for apps.

There are several good reasons to commit a lockfile:

  • Reproducibility: A lockfile, as its name implies, locks the version of each dependency (and sub-dependency) to the specific version from your latest install command, even if your package.json has a loose semver range (like *, or ^#.#.#)

    • No more "works on my machine" arguments that are caused by npm install being run on different days and grabbing different dependencies
    • You can be sure that your CI, local PC, and other devs all have the exact same version of all dependencies
  • Security: Although there are also some security risks with lockfiles themselves, used correctly and with care, there is some additional security afforded by their use; if you are locked to a good version of a package, and that author gets hacked and starts publishing a bad version, your build pipeline won't be affected unless somebody manually updates to that version and commits the lockfile.

    • There are also multiple security tools and systems that can automatically scan lockfiles for known security issues; this is now baked into Github, for example.

Yarn does a great job of summarizing these benefits in this article.

However, there is also a very specific argument against committing lockfiles, if you are building a NPM package. The reason being that, if your project is a package and is being installed as a dependency, the lockfile is not considered, only the package.json file is.

The reason why this is problematic, is that you can actually end up with that "works on my machine" issue, but with an added false sense of security; when you are developing your package locally, the lockfile is respected and everything works with the exact versions you need, but when a project that consumes your package installs it as a dependency, it just grabs whatever matches your package.json semver settings, which might allow for a dependency version that breaks your code. Sindre Sorhus, who is one of the most prolific NPM package creators, summarizes the issue here.

In these instances, it might be better to omit the lockfile, and instead very narrowly define the semver in your package.json, perhaps even specifying an exact version.

List installed packages

Courtesy of jkomyno

# NPM
npm list -g --depth 0

# Yarn
yarn global list

Find the binary of a given package

Many devs already know you can use npx {packageName} to run with a preference for using local binaries before downloading and executing a global install, but what about locating the actual binary path?

  • NPM

    • All local binaries (nearest bin dir) (echo path): npm bin

      • Note: This is where npm will install binaries if called from the current working directory, not necessarily where they are already installed.
    • Specific binary: you can use variable substitution with npm bin if you really need the path, otherwise just use npx
  • Yarn

    • Pretty similar to NPM (above)
    • All local binaries (echo path): yarn bin

      • This has the same disclaimer as npm bin
    • Specific binary (echo path): yarn bin {package}
    • Run a specific binary: yarn {package}

      • Unlike npm, yarn does not require something like npx be used to run against a local command

Find top level package that is using another

If we have package {top-level} that is using {sub-depend}, but we don't know that - all we know is that one of our top packages is using "sub-depend", we can find it out by using:

npm ls {sub-dependency-name}

List versions

npm -version

Get the version of a package

NPM

npm list {packageName}

Yarn

yarn list --pattern {packageNameOrPattern} Or... yarn list | grep {packageNameOrPattern} Or... yarn global list --pattern {packageNameOrPattern}

Install a very specific version of a package (from CLI)

You can actually use similar syntax as a package.json file - e.g. tslint@^5.0.0.

Updating / upgrading packages used in package.json

  • NPM

    • You can use npm update to pull in updated packages (will also update your package-lock.json automatically)
    • You can use npm outdated to see what your package.json is requesting VS what is published

      • Good to use this to double-check after running npm update, since npm update requests based on your package.json semver rules, not necessarily what is newest
    • For upgrading to the absolute latest, ignoring package.json, there is no built-in command (unlike Yarn)

      • The easiest way to do it by hand, is to edit the package.json file to have * as the semver for any dependency you want to have updated to the latest, and then run npm update again.

        • Since npm knowns * is invalid, it will update and then overwrite the entry
      • Another option is to call npm install PACKAGE_NAME@latest for each dependency you want updated
      • For an automated / interactive 3rd party solution, you could check out one of these:

  • Yarn:

    • Upgrade to latest specified by package.json: yarn upgrade
    • Same as above, but interactively: yarn upgrade-interactive
    • Upgrade to absolute latest, ignoring package.json (for example, major version bump): yarn upgrade-interactive --latest
    • You can use yarn outdated to see what your package.json is requesting VS what is published

      • See notes above on npm outdated, since this works similarly

Installing a specific version

  • NPM

    • npm install {packageName}@{semVerPattern}
  • Yarn

    • yarn add {packageName}@{semVerPattern}

How to deal with nested dependency versions

A somewhat common issue is trying to force a direct dependency (listed under dependencies or devDependencies in package.json) to use a specific version of their dependency.

This is not something you normally dictate - it is normally handled automatically by NPM or Yarn - but sometimes you might want to force a certain sub-dependency version due to a vulnerability; for example, if you use my-dependency which has a nested dependency of my-sub-depend locked at v0.0.1, which has a severe vulnerability patched in v0.0.2.

There are multiple ways to approach this, and the best starting spot is this S/O Question.

  • NPM

    • Use Shrinkwrap file

      1. Run npm shrinkwrap
      2. Manually edit the auto-created npm-shrinkwrap.json file

        • Use Semver targeting to force the new version you want
      3. Run npm install again
    • Use an automated solution, like npm-force-resolutions

      • This lets you use the package.json -> resolutions approach, that natively works with Yarn (see below)
  • Yarn

    • Yarn is way easier to use overrides with, in comparison to NPM
    • Just add resolutions object to package.json with overrides

When in doubt and messed up beyond repair...

npm cache clean -force

When REALLY messed up

rm -rf node_modules
npm cache clean -force
npm install

Installing peer-dependencies

Many packages, especially lint configs, will require other dependencies (peer dependencies) but will not install them automatically. You could manually figure out what's needed (for example, by running npm ls) and manually install one by one, or use a tool like install-peerdeps.

# See: https://www.npmjs.com/package/install-peerdeps#usage

# NPM
npm install -g install-peerdeps

# Yarn
yarn global add install-peerdeps

install-peerdeps --dev {package}
# OR
install-peerdeps {package}
# OR
install-peerdeps <package>[@<version>]

You can list peer dependencies needed by a package by using

# NPM
npm info "{package}" peerDependencies

Using global modules / packages

You can use globally installed packages by taking advantage of link - which basically just symlinks from the global folder to your project directory. Once something is installed globally, you can simply run npm link {packageName} in the directory where you want to be able to access it.

WARNING: The much preferred way to do this is with npx, which will use your project's dependency first, if it has it.

Currently, Yarn will allow linking of dev packages (e.g. yarn link in dev, yarn link {name} in test), but tends to have issues with globally installed versions (GH issue).

NPM Install Errors

  • "No prebuilt binaries found"

    • There is probably a dependency that was built using C++ or other codebase and is missing a prebuilt binary for your versions of node/ABI#. Check your ABI and compare against what is hosted as a prebuilt binary.

      • If you can't find a prebuilt to use, just build yourself (check dependency's package.json and .gyp for details). You will probably also need build tools installed, depending on OS:

        npm install --global --production windows-build-tools
  • General build errors ("MSBuild", etc)

    • Make sure that you have build tools installed (see above)

      • Make sure built-tools install WORKED

        • Make sure to run as Admin
        • Check log, and if necessary, manually run the installer it downloads
    • You can switch what version of MSVC you are targeting:

      • For example: npm config set msvs_version 2015 -g
    • Try to get Node to use a prebuilt-binary instead of building from scratch

      • Check the log to see why node is trying to rebuild/build

        • For example, is a firewall blocking the binary download?
        • Some install scripts will let you specify a binary source URL
      • A quick hack if you can find a pre-built binary to download, is to save it to the corresponding npm-cache folder, and then run npm rebuild {packageName} before trying to re-install.

        • You should see Cached binary found at ... if this trick worked
        • Found via this comment

List tasks

npm run

Markdown Source Last Updated:
Wed Nov 11 2020 15:20:44 GMT+0000 (Coordinated Universal Time)
Markdown Source Created:
Tue Aug 27 2019 07:54:31 GMT+0000 (Coordinated Universal Time)
© 2020 Joshua Tzucker, Built with Gatsby
Feedback