npm recipes
npm workspaces
npm workspaces are defined in package.json
as an array of paths, possibly including wildcards (*
):
{
"workspaces": [
"packages/*"
]
}
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.
Miscellaneous
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
...is 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'"
}
}