Node.JS provides one of the easiest to learn and use and at the same time productive programming environments: A small but flexible programming language, that allows to create universal applications, built-in streaming and non-blocking IO, backed by a rich and very actively developed ecosystem of sophisticated open-source tools and libraries, on top of one of the fastest runtimes that is always getting even faster.
Install Node.js using a package manager, for example on OS X via Homebrew:
$ brew install node
Use n if you want to run different Node.JS versions on your machine.
For partner-facing projects, pick a widely known language with broad and long-term community and tool support (including linters, source maps, code coverage measurements, published books, and an active developer community) like CoffeeScript or ES6.
For internal projects you can use more experimental languages, like LiveScript.
Initialize a valid package.json file
npm init in your application’s directory.
The package folder structure should follow these conventions:
|bin||any command-line tools that your NPM module provides go here|
|src||your source code goes here. This folder should not be shipped via NPM.|
Your main directory should contain these files:
|CONTRIBUTING.md||developer documentation, targeted at maintainers of the library|
|LICENSE||a permissive license that allows usage in commercial projects (e.g. ISC, MIT)|
|README.md||main documentation, targeted at users of the library|
|package.json||the NPM config file|
Make copious use of badges to indicate build status, dependency currentness, code coverage, code quality, and other metrics in your readme.
node_modules directory into Git
by adding these directories to your
Specify the files to be shipped in an NPM module via the
section in your
Don’t ship development-only files like tests, source code etc.
Separate development and production dependencies from each other
by putting them into the
Use david for tracking whether your dependencies are up to date. If you work on an open-source project, please add a badge that indicates whether your dependencies and dev-dependencies are up-to-date.
Use @charlierudolph`s dependency-lint tool to prune out unused dependencies.
For your own code, try to follow semantic versioning, like the rest of the Node ecosystem.
NPM provides a wide range of ways to specify the versions of your dependencies in more or less flexible ways. Unfortunately, there is no easy to use single best solution for more serious (enterprise-grade) use cases, so let’s discuss the various options in more detail to give you some guidance:
"fsextra": "*" or
motivation: automatically use the latest state of the art on each deploy
conclusion: this is highly unsafe, and should never be used. Any breaking change in any of your dependencies will be picked up automatically and affect your application.
motivation: your dependencies get automatically updated to the latest semantically “safe” versions on each deploy
^1.2.3of a dependency, your could actually be using
1.7.9and wouldn’t know it. The problem here is that such vast version changes are very likely to introduce subtle changes in APIs and functionality that you are not aware of. And the only time you will notice this is when a new production deploy suddenly stops working.
package.jsonfile with this setup.
motivation: lock down the APIs that your code talks to, but leave management of your dependencies’ stability and updates up to them.
npm config set save-exact true to configure your NPM client
to always store exact version numbers from now on.
example: by using a shrinkwrap
motivation: lock down the exact versions of all external APIs
Together with NPM’s policy that existing versions can never be changed, this can make guarantees that your code will always work exactly the same.
# remove `node_modules` from `.gitignore`
rm -rf node_modules
npm install --ignore-scripts
git add . && git commit -a
# add all new files to .gitignore
# when deploying on production, you just have to run "npm rebuild"
motivation: store all of the source code that your application needs to run in one place, so that it is deployable as-is.
npm rebuildon the target machine
more info: here
tips: To avoid cluttering PRs with dependency source code, submit them on your own before the PR. The code review can assume the correct dependencies are in place.
actively developed projects should do (3) and (4) together: use exact versioning in package.json to document what exact API versions your code is designed against, plus a shrinkwrap to lock down all versions of all dependencies for stability.
projects in maintenance mode should do (3), (4), and (5) together
this applies equally to libraries (code that is used by other Node.JS code) as well as servers (code that runs by itself). This distinction is artificial and doesn’t hold up in real life. Almost all “servers” should (and do) provide JS APIs to call them from other code Node code in addition to running them by themselves from the command line. Examples: NPM itelf, Mocha, Cucumber-JS, etc.
dependencies of all NPM modules should be updated at least once a month, ideally using o-tools.
Simplify your release process by defining version and publish lifecycle scripts in your package.json:
"postpublish": "git push && git push --tags",
"prepublish": "<call your build script here>",
"preversion": "npm test && npm run update"
Then, to release a new version of your NPM module, call:
$ npm version <patch|minor|major>
$ npm publish
Set up CI to
npm publish your package when pushing to the
This can be accomplished on CircleCI by adding the following to your
- npm set //registry.npmjs.org/:_authToken $AUTH_TOKEN
- npm publish
Then set the
AUTH_TOKEN environment variable in the project settings in CircleCI. Ping Alex David, or Kevin Goslar for Originate’s