Home

Awesome

npm Style Guide

Opinionated ​npm Style Guide​ for teams by De Voorhoede.

npm style guide

Purpose

This guide provides a set of rules to better manage, test and build your npm modules and project scripts. It should make them

Table of Contents

Use nvm to manage node versions

Why?

With nvm you can have multiple different versions available and switch to the one that suits better your project.

How?

To install or update nvm, you can use the install script using cURL:

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.0/install.sh | bash

For Windows check nvm for windows.

If everything goes well, you can now install a specific node version.

nvm install stable
nvm install vX.Y.Z
nvm alias default stable

It’s also easy when updating a newer version, copying your existing global modules.

nvm copy-packages <previous-version>

↑ back to Table of Contents

Configure your npm personal info

Why?

When creating a new package npm init your defaults will be already included on the scaffolding.

How?

npm config set init-author-name "{name}"
npm config set init-author-email "{email}"

Check npm config docs, for more info.

You can use cat ~/.npmrc to check your current definitions.

↑ back to Table of Contents

Use save exact option

Why?

By default, installing a package with the --save or --save-dev option, npm saves the package version with ^ prefix, meaning that will update minor versions if available. While this is a good idea as is, this makes it possible for different developers having different versions of the same package and making it harder to debug if there is inconsistency. Defining the save-exact option prevents this. More info npm config docs.

How?

npm config set save-exact

↑ back to Table of Contents

Specify engines on package.json

Why?

Specifying engine versions for your module, warns the user if he is not using a supported version. This is specially important for ensuring npm@3 flat tree dependency on Windows, or ES2015 features that your scripts require on node.

How?

In package.json:

"engines" : {
  "node" : "5.10.0",
  "npm" : "3.8.5"
}

Preventing the user from using your module is also possible with check-pkg-engines.

↑ back to Table of Contents

Avoid installing modules globally

NPM first tries globally installed modules before looking for local ones. Globally installed modules are shared between projects and might not match the required version for the project.

Why?

How?

# recommended: install locally
npm install --save-dev grunt-cli grunt

and use in package.json:

"scripts": {
  "icons": "grunt grunticon"
}
# avoid: don't install modules globally
npm install -g grunt-cli grunt

↑ back to Table of Contents

Use npm modules for system tasks

Why?

When you use system specific commands like rm -rf or &&, you are locking your tasks to your current operating system. If you want to make your scripts work everywhere think about Windows developers also.

How?

Use npm modules with node that mimic the same tasks but are system agnostic. Some examples:

↑ back to Table of Contents

Avoid shorthand command flags

npm and npm modules with a command-line interface support different options using fully written out and / or shorthand flags. For instance, instead of npm install --save-dev you can use the shorter npm i -D. For npm test you can use simply npm t. But npm start is not the same as npm s, as that's an alias for npm search. So while you can use these shorthands in your daily routine, you should avoid them in scripts and documentation shared with other developers.

Why?

How?

Always prefer fully written command flags over shorthand. Example using uglifyjs:

# recommended
uglify index.js --compress --mangle --reserved '$' --output index.min.js
# avoid
uglifyjs index.js -c -m -r '$' -o index.min.js

↑ back to Table of Contents

Use standard script names

npm lets you define custom scripts. You can give these scripts any name you like, but you should stick to standard names when you can.

Why?

Using standard script names creates a predictable script API, which makes your project easier to use by other developers. When used consistently between projects a user doesn't even need to read the documentation or package.json to know which scripts are available.

How?

npm start and npm test are predefined aliases for custom scripts. In addition use of build, deploy and watch are widely spread within the developer community. You should use these script names as follows:

In package.json:

/* recommended: standard script names */
{
  "scripts": {
    "build": "...",
    "deploy": "...",
    "start": "...",
    "test": "...",
    "watch": "..."
  }
}

/* avoid: */
{
  "scripts": {
    "bundle": "...",
    "upload": "...",
    "serve": "...",
    "check": "...",
    "watcher": "..."
  }
}

↑ back to Table of Contents

Write atomic scripts

Each script should be only responsible for one action.

Why?

How?

Separate each step of the script to an individual script. For example a "generate icon" script can be split into atomic script like "clean directory", "optimize SVGs", "generate PNGs" and "generate data-uris for SVGs".

↑ back to Table of Contents

Group related scripts by prefix

Bundle your scripts with a prefix so you can execute them all at once.

Why?

How?

In package.json:

/* recommended: group related scripts by prefix */
scripts: {
	"test": "npm run test:eslint && npm run test:unit && npm run test:e2e",
	"test:eslint": "eslint src/**/*.js",
	"test:unit": "tape --require dist/index.js src/**/*.test.js",
	"test:e2e": "karma start test/config.js"
}

/* avoid */
scripts: {
	"eslint": "eslint src/**/*.js",
	"tape": "tape --require dist/index.js src/**/*.test.js",
	"karma": "karma start test/config.js",
}

Bundled scripts can be executed (in parallel or in sequence) using npm-run-all:

/* recommended: use `npm-run-all` to run all bundled scripts */
scripts: {
	"test": "npm-run-all test:*",
	"test:eslint": "eslint src/**/*.js",
	"test:unit": "tape --require dist/index.js src/**/*.test.js",
	"test:e2e": "karma start test/config.js"
}

↑ back to Table of Contents

Document your script API

Why?

How?

Document your script API in the project's README.md or CONTRIBUTING.md as those are the first places contributors will look. Describe what each task does using a simple table:

`npm run ...` | Description
---|---
task | What it does as a plain human readable description.

An example:

npm run ...Description
buildCompile, bundle and minify all CSS and JS files..
build:cssCompile, autoprefix and minify all CSS files to dist/index.css.
build:jsCompile, bundle and minify all JS files to dist/index.js.
startStarts a server on http://localhost:3000.
testRun all unit and end-to-end tests.

↑ back to Table of Contents


License

CC0

De Voorhoede waives all rights to this work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law.

You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission.