10 habits of a happy node.js developer

Original author: Hunter Loftis
  • Transfer

By the end of 2015, JavaScript developers had a huge number of tools at their disposal. It is easy to get lost in this ecosystem, therefore successful teams follow developed rules that allow you not to waste time and maintain the health of projects. Under the cut, a 2016 article translation from the Heroku team, in which they talk about ten habits of web developers, for whom everything works and nothing hurts. Most likely you already know 80% of what is written - the more interesting it will be for you to read about the remaining two tricks!

1. Start a new project with npm init

This command will immediately create the correct package.json based on the name of the project directory and your answers to the wizard's questions:

$ mkdir my-awesome-app
$ cd my-awesome-app
$ npm init --yes

Using the --yes flag allows you not to answer wizard questions, and in the engines field of the resulting package.json, you can immediately install the required version of the node ( node -v ):

"engines": {
  "node": "4.2.1"

2. Use smart .npmrc

By default, npm does not write installed dependencies in package.json (and you should always keep track of dependencies!).

If you use the --save flag to automatically update package.json , npm will save the dependency name with the ^ prefix . Semantic versioning puts your dependencies at risk, because with a clean installation, other versions of the dependencies may be installed in the project, and who knows what bugs and problems might be in them. This method is good during development, but not in production. One solution is to keep the exact version of the dependency:

$ npm install foobar --save --save-exact

Better yet, change the global npm settings to ~ / .npmrc so that everything happens automatically:

$ npm config set save=true
$ npm config set save-exact=true
$ cat ~/.npmrc

With this configuration, installing the dependencies will keep the exact version and your project will never overtake the creepy “version drift”!

If you prefer the latest versions of dependencies during development, plus freezing for selling, then you can use the shrinkwrap function . Such a configuration will require a bit more effort, but allow a more flexible approach to versioning dependencies.

3. Watch out for the departing ES6 train

Starting with version 4 of Node.js, you can use many ES6 features. Start using simple and convenient syntax improvements now that will make your code simpler and easier to understand:

let user = users.find(u => u.id === ID);
console.log(`Hello, ${ user.name }!`);

4. Stick to lowercase

Some languages ​​recommend naming files in the same way as classes. For example, a file implementing MyClass is proposed to be called MyClass.js . Do not do this in node. Use lower case:

let MyClass = require('my-class');

Node.js is a rare example of a Linux program with excellent cross-platform support. Although OSX and Windows will consider the files myclass.js and MyClass.js to be the same file, Linux will not. If you want to write cross-platform code, you need to name the files in the same register that you use for require .

The easiest way to do it right is to use lower case, that is, my-class.js (translator's note: or my_class.js , which is still more popular among programmers than css notation).

5. Cluster your application

Since the node process is limited to one core and one and a half gigabytes of RAM, deploying a non-clustered application to a powerful server is a waste of useful resources. To use multiple cores and lots of memory, add clustering support to your application. Even if you are now running the application on a single-core vps with a gig of memory, adding clustering will be a good foundation for the future.

The best way to find the optimal number of processes is, of course, testing. But for starters, the default value offered by the platform is suitable. Well and adequate fallback, of course:

const CONCURRENCY = process.env.WEB_CONCURRENCY || 1;

Using clustering eliminates the need to reinvent the wheel for flow control. If you like file separation between “master” and “worker”, then try forky . If you prefer a single entry point, then throng .

6. Watch out for environment variables

Use environment variables instead of config files. To do this, install node-foreman :

$ npm install --save --save-exact foreman

Then create a Procfile to indicate the type of application:

web: bin/web
worker: bin/worker

And install alias to run:

"scripts": {
  "start": "nf start"

Now, to change the environment settings, just create (and add to .gitignore ) a file named .env , which will be automatically loaded by node-foreman :


With such settings, one npm start command is enough to start the web and worker processes, and then apply settings to them in accordance with the environment variables. It is much simpler than 'config / abby-dev.js', 'config / brian-dev.js', 'config / qa1.js', 'config / qa2.js', 'config / prod.js', etc. .

7. Avoid trash

Node.js (represented by the V8 engine) uses a "lazy" and "greedy" garbage collector. With a default limit of one and a half gigabytes, he often waits until the last before freeing up unused memory. If your used memory is gradually growing, this may not be its leak, but rather the standard behavior of the node garbage collector.

For better control over the garbage collector, you can put commands for the V8 engine in Procfile :

web: node --optimize_for_size --max_old_space_size=920 --gc_interval=100 server.js

This is especially important if your application is running on a machine with less than one and a half gigabytes of available memory. For example, for a container with 512 megabytes of memory, an argument string might look like this:

web: node --optimize_for_size --max_old_space_size=460 --gc_interval=100 server.js

8. Use hooks

“Lifecycle scripts” in node.js provide extensive automation capabilities. For example, if you need to run something before building the application, you can use the preinstall script . Need to build assets using grunt, gulp, browserify or webpack? Use the postinstall script . All these scripts can be set directly in package.json :

"scripts": {
  "postinstall": "bower install && grunt build",
  "start": "nf start"

And of course you can use environment variables to manage your scripts:

"postinstall": "if $BUILD_ASSETS; then npm run build-assets; fi",
"build-assets": "bower install && grunt build"

If the scripts become too complex - transfer them to files:

"postinstall": "scripts/postinstall.sh"

Important: scripts in package.json are executed with ./node_modules/.bin automatically added to PATH , so you can directly call locally installed npm packages, such as webpack. This eliminates the need to install packages globally at all.

9. Only git the important bits

I liked this title so much that I left it without translation. A beautiful play on words is “only important bits” = “add only what’s important to git”. Most applications consist of two types of files: which can or cannot be generated automatically. When you use a version control system, avoid adding files to it that can be generated automatically.

For example, your application has a node_modules directory with dependencies installed. Yes, there are people who add it to the version control system! No need to do this. Specifying the correct dependency versions in package.json is much more reliable since npm install does not clear node_modules, and if there are already files from the version control system, trouble may happen.

Also, adding generated files makes a lot of noise in the logs and notifications of your repository. Moreover, some dependencies require compilation during installation, so adding the installed version to the repository makes your application unsortable and can lead to strange errors.
For the same reasons, you should not add bower_components or compiled grunt assets. If the node_modules directory is already added to the version control system in the project , then you can always remove it, for example, like this:

$ echo 'node_modules' >> .gitignore
$ git rm -r --cached node_modules
$ git commit -am 'ignore node_modules'

I also usually add npm logs to ignore so as not to clutter up the code:

$ echo 'npm-debug.log' >> .gitignore
$ git commit -am 'ignore npm-debug'

By ignoring these less important files, you reduce the size of the repository, simplify commits, and do not get merge conflicts.

10. Simplify

Predictions in IT are a thankless task. But I still do one thing. I predict that for JavaScript, 2016 will be a year of simplification.
More and more programmers are simplifying the architecture of their solutions. Monolithic MVC solutions are being replaced by a static frontend, which is so convenient to distribute via CDN, and a Node.js backend for dynamic data.

We also began to notice how complex assembly systems complicate our projects. At the forefront, developers are simplifying these decisions, in particular by using npm scripts instead of bower, gulp and grunt.

And finally, in 2016 we will simplify the code we wrote. In some cases, this will be a rejection of unnecessary features, as Douglas Crockford showed in his The Better Parts. Or, conversely, simplification will come from adding new functionality. Like my favorite async and await. They are not in the node yet, but you can always use a transporter, for example BabelJS.

Try not to compete with each other in how many new technologies can be crammed into one project, but to focus on simplifying your work.

Also popular now: