Skip to content

Back to Toolbox

npm recipes

npm workspaces

npm workspaces are defined in package.json as an array of paths, possibly including wildcards (*):

"workspaces": [

Run command build in all workspaces (but not in the root folder):

npm run build --workspaces --if-present

The --if-present flag instructs npm to skip workspaces that don’t have the build script defined. Without it, npm throws an error for missing scripts.

Gotcha: workspace scripts are run in sequence

The npm run <command> --workspaces runs <command> in sequence, which makes it impossible to run watch-type tasks, which are long-running and blocking subsquent commands.

Until npm gains the ability to run things in parallel, the workaround is to use npm-run-all (or the more updated npm-run-all2):

"scripts": {
"watch": "npm-run-all watch:*",
"watch:w1": "npm run watch --workspace=w1",
"watch:w2": "npm run watch --workspace=w2",


Weaning yourself off yarn

Here are plain npm alternatives to yarn commands.

Install a local package

# Instead of:
yarn add [--dev] <package>

# Write:
npm install [--save-dev] <package>

Install a global package

# Instead of:
yarn global add <package>

# Write
npm install -g <package>

Publish a package to npm

# Instead of:
yarn publish

# Write:
npm version [major|minor|patch]
npm publish

Run a script

# Instead of:
yarn <script-name>

# Write:
npm run-script <script-name>

# Or, shorter:
npm run <script-name>

Run a local binary

# Instead of:
yarn <bin-name>

# Write:
npx <bin-name>

Use the --no-install flag prevent npx from fetching a missing binary from the npm registry.


Gotcha: Glob expansion in scripts

When running npm run <script-name>, the attached command gets executed within the shell linked at /bin/sh rather than your current shell. A pattern such as:

{src,test}/**/*.js expanded differently in bash, versus zsh, leading to subtle bugs. Instead, defer the glob expansion to the particular tool you're running, if it has this feature:

"scripts": {
// Instead of:
"lint": "eslint {src,test}/**/*.js",

// Write it with quotes:
"lint": "eslint '{src,test}/**/*.js'"