Node.js Best Practices

Written by: Gergely Nemeth

This article was originally published on RisingStack by Gergely Nemeth. With their kind permission, we’re sharing it here for Codeship readers.

In this article, we will go through the most important Node.js best practices, topics that you should care about and educate yourself in. Let’s start!

Use ES2015

Last year we advised you to use ES2015 -- however, a lot has since changed.

Back then, Node.js v4 was the LTS version, and it had support for 57 percent of the ES2015 functionality. A year passed and ES2015 support grew to 99 percent with Node v6.

If you are on the latest Node.js LTS version, you don't need Babel anymore to use the whole feature set of ES2015. But even with this said, you’ll probably still need it on the client side!

For more information on which Node.js version supports which ES2015 features, I'd recommend checking out node.green.

Use Promises

Promises are a concurrency primitive, first described in the `80s. Now they are part of most modern programming languages to make your life easier.

Imagine the following example code that reads a file, parses it, and prints the name of the package. Using callbacks, it would look something like this:

fs.readFile('./package.json', 'utf-8', function (err, data) {
  if (err) {
    return console.log(err)
  }
  try {
    JSON.parse(data)
  } catch (ex) {
    return console.log(ex)
  }
  console.log(data.name)
})

Wouldn't it be nice to rewrite the snippet into something more readable? Promises help you with that:

fs.readFileAsync('./package.json').then(JSON.parse).then((data) => {
  console.log(data.name)
})
.catch((e) => {
  console.error('error reading/parsing file', e)
})

Of course, for now, the fs API does not have a readFileAsync that returns a Promise. To make it work, you have to wrap it with a module like promisifyAll.

Use the JavaScript Standard Style

When it comes to code style, it is crucial to have a company-wide standard, so when you have to change projects, you can be productive starting from day zero without having to worry about building the build because of different presets.

At RisingStack, we have incorporated the JavaScript Standard Style in all of our projects.

With Standard, there are no decisions to make, no .eslintrc, .jshintrc, or .jscsrc files to manage. It just works. You can find the Standard rules here.

Use Docker

You can think of Docker images as deployment artifacts -- Docker containers wrap up a piece of software in a complete filesystem that contains everything it needs to run: code, runtime, system tools, system libraries, anything you can install on a server.

But why should you start using Docker?

  • It enables you to run your applications in isolation.

  • As a conscience, it makes your deployments more secure.

  • Docker images are lightweight.

  • They enable immutable deployments.

  • With them, you can mirror production environments locally.

To get started with Docker, head over to the official Getting Started tutorial. Also, for orchestration, we recommend checking out our Kubernetes best practices article.

Monitor Your Applications

If something breaks in your Node.js application, you should be the first one to know about it, not your customers.

One of the newer open-source solutions is Prometheus that can help you achieve this. Prometheus is an open-source systems monitoring and alerting toolkit originally built at SoundCloud. The only downside of Prometheus is that you have to set it up and host it for yourself.

If you are looking for on out-of-the-box solution with support, Trace by RisingStack is a great solution developed by us.

Trace will help you with:

  • alerting

  • memory and CPU profiling in production systems

  • distributed tracing and error searching

  • performance monitoring

  • and keeping your NPM packages secure

Use Messaging for Background Processes

If you are using HTTP for sending messages, then whenever the receiving party is down, all your messages are lost. However, if you pick a persistent transport layer, like a message queue to send messages, you won't have this problem.

If the receiving service is down, the messages will be kept and can be processed later. If the service is not down but there is an issue, processing can be retried so no data gets lost.

An example: Say you'd like to send out thousands of emails. In this case, you would just have to gather some basic information like the target email address and the first name, and a background worker could easily put together the email's content and send them out.

What's really great about this approach is that you can scale it whenever you want, and no traffic will be lost. If you see that there are millions of emails to be sent out, you can add extra workers, and they can consume the very same queue.

You have lots of options for messaging queues:

!Sign up for a free Codeship Account

Use the Latest LTS Node.js Version

To get the best of the two worlds (stability and new features), we recommend using the latest LTS (long-term support) version of Node.js. To easily switch Node.js versions, you can use NVM. Once you installed it, switching to LTS takes only two commands:

nvm install 6.11.5
nvm use 6.11.5

Use Semantic Versioning

We conducted a Node.js Developer Survey a few months ago, which allowed us to get some insights on how people use semantic versioning.

Unfortunately, we found out that only 71 percent of our respondents uses semantic versioning when publishing/consuming modules. This number should be higher in our opinion; everyone should use it! Why? Because updating packages without SemVer can easily break Node.js apps.

Versioning your application/modules is critical. Your consumers must know if a new version of a module is published and what needs to be done on their side to get the new version. This is where semantic versioning comes into the picture. Given a version number MAJOR.MINOR.PATCH, increment the:

  • MAJOR version when you make incompatible API changes,

  • MINOR version when you add functionality (without breaking the API),

  • PATCH version when you make backward-compatible bug fixes.

MPM also uses SemVer when installing your dependencies, so when you publish modules, always make sure to respect it. Otherwise, you can break others' applications!

Secure Your Applications

Securing your users' and customers' data should be one of your top priorities. In 2016 and 2017, hundreds of millions of user accounts were compromised as a result of low security.

To get started with Node.js Security, read our Node.js Security Checklist, which covers topics like:

  • Security HTTP Headers

  • Brute Force Protection

  • Session Management

  • Insecure Dependencies

  • Data Validation

After you’ve embraced the basics, check out my Node Interactive talk on Surviving Web Security with Node.js!

Learn Serverless

Serverless started with the introduction of AWS Lambda. Since then, it's growing fast, with a blooming open-source community. In the next years, Serverless will become a major factor for building new applications. If you'd like to stay on the edge, you should start learning it today.

One of the most popular solutions is the Serverless Framework, which helps in deploying AWS Lambda functions.

If you have any questions about the article, find me in the comments section!

Stay up to date

We'll never share your email address and you can opt out at any time, we promise.