Welcome to my first ever blog post on CodeSmash.io. Now, this article is a reproduction of a query that I once received on Quora. The question was, "What are the best practices for Node.js apps?". Node has taken center stage over the past couple of years and it is no surprise that enterprise level companies are embracing its benefits and bringing more and more products from legacy systems, to a Node-centric ecosystem. When writing Node.js apps however, you should follow a set of best practices that will always result in a smoother and peaceful development, deployment and maintenance experience.

So, here's my list of best practices for Node.js apps. These are obviously not comprehensive but are a great start.

  • Always specify a compatible version(s) of Node.js for your app in the package.json using the “engines” option. e.g. { "engines" : { "node" : ">=6.2.0 <7.0.0" } }. This ensures that during deployment you get the version of Node.js that supports language/module features that you’ve used in development.
  • When installing dependencies, use the —save-exact flag to ensure versions are locked. The JS ecosystem evolves at the speed of thought and this means, breaking changes to module interfaces/APIs are introduced by developers from time to time. If versions are not locked, then an incompatible version may end up breaking your app during redeployment or maintenance. This obviously does not mean that you should not look into newer versions of your dependencies from time to time. You can also use the .npmrc file to permanently enable the save-exact feature.
  • Use nodemon when developing apps. This speeds up development by automatically restarting your app, the moment you save files.
  • Configure your scripts in package.json. The ‘start’ script is particularly useful among others.
  • When deploying your app, use a utility like ‘forever’ or ‘pm2’ to ensure your app restarts if it crashes out due to some reason.
  • Modularize code by breaking it down into manageable modules. That is at the core of application design when using Node.
  • Always manage your errors in an elegant way. This means ‘console.log()’ statements are a no no in production. Use a third party utility like Winston (for ExpressJS) for logging errors and other messages. These can then be used in conjunction with utils like Papertrail in deployment to monitor apps.
  • You can also implement third party app monitoring service like NewRelic or Keymetrics to closely monitor your app once deployed.
  • Stay away from callback hell and use Promises, Async/Await. They help you in writing optimized and manageable code. Besides this, errors that are often lose deep inside nested callbacks are correctly captured when Promises are used instead.
  • Static files such as stylesheets and other assets should be served using a pure web server like NginX instead of routing them through your Node app. Your Node app can sit behind NginX as a proxy.
  • To start with, you can store your credentials such as API keys, tokens etc. in environment variables and NOT in files. PaaS services such as Heroku offer an easy way to configure environment variables. Though this is safer than using files, the best way is to use a Key Management System (KMS) which actually offers the most secure token/credential management. Usually, during development, we store credentials in text files such as JSON files. However, the same should NEVER be pushed to production. A KMS offers the best way to store credentials in a production environment. Additionally always ensure your development time JSON files where you’re storing tokens and credentials are never pushed on Github repos or other versioning/collaborative spaces.
  • When using git for version control, add your node_modules and any other files that may contain credentials/tokens etc. in the .gitignore file to ensure they’re not pushed on Github or your deployment environment, such as on Heroku.
  • Prefer using async version of methods. Some methods in Node.js such as in the ‘fs’ module offer both an async and a synchronous version. Prefer the async version.
  • Import modules right at the beginning of a JS file and not within methods.
  • Use NVM or ’n’ to manage and install multiple versions of Node in your development environment. Can also be used on EC2/DO Droplets.
  • Though not directly related to Node.js, when using cloud compute services like Amazon EC2, regularly monitor your usage and billing. This is specially for newbies who are just starting to develop and deploy Node apps on the cloud. If you’re just playing & learning deployment, make sure you spin down your cloud instance when not in use. I’ve known people who simply forgot to shut down the instance and were presented with hefty bills by AWS at the end of the month.

If you have any questions or need my help with learning or writing Node.js apps, feel free to touch base on Twitter (@sachinbee) or write to me on mailme@sachinbhatnagar.com.