Node.js Project Best Practice

Overview

Having been using node.js for several years, I have something to share with you. Hope it will save your time.

Lock dependencies

Your code must be identical across all environments but amazingly NPM lets dependencies drift across environments be default – when you install packages at various environments it tries to fetch packages’ latest patch version. Overcome this by using NPM config files , .npmrc, that tell each environment to save the exact (not the latest) version of each package. Alternatively, for finer grain control use NPM” shrinkwrap”. *Update: as of NPM5 , dependencies are locked by default. The new package manager in town, Yarn, also got us covered by default

For team work, I suggest to check-in node modules into your source code (git/snv/etc). To make sure everyone and the production site using the same version of node modules. And another reason is that, some modules are downloaded from github. And it may be not exist anymore after servery month or years.

Keep Your Promises

Node 8 supports the long-awaited async and await keywords without opting in to experimental features. This feature builds on top of Promises allowing you to write asynchronous code that looks like synchronous code and has the same error handling semantics, making it easier to write, easier to understand, and safer.

You can write your callback in this way

1
2
3
4
5
async function getAlbums(() {
const books = await getBooks();
const albums = await getAlbums(books);
return getPhotosForAlbums(albums);
}

Automate Your Code Formatting

We’ve all collectively spent too much time formatting code, adding a space here, aligning a comment there, and we all do it slightly different than our teammate two desks down. This leads to endless debates about where the semicolon goes or whether we should use semicolons at all.

You can use VSCode, which has the ability to format the code.

HTTPS all the things

As web engineers, there is no reason we shouldn’t default all traffic in our applications to using HTTPS. In an express application, there are several things you need to do to make sure you’re serving your site over https.

Be stateless

Store any type of data (e.g. users session, cache, uploaded files) within external data stores. Consider ‘killing’ your servers periodically or use ‘serverless’ platform (e.g. AWS Lambda) that explicitly enforces a stateless behavior.

Otherwise, failure at a given server will result in application downtime instead of a just killing a faulty machine. Moreover, scaling-out elasticity will get more challenging due to the reliance on a specific server.

Set NODE_ENV production

Set the environment variable NODE_ENV to ‘production’ or ‘development’ to flag whether production optimizations should get activated – many NPM packages determining the current environment and optimize their code for production.

For example, Setting NODE_ENV to “production” makes Express:

  • Cache view templates.
  • Cache CSS files generated from CSS extensions.
  • Generate less verbose error messages.

Useful Tools

IDE - VSCode

Visual Studio Code is a lightweight but powerful source code editor which runs on your desktop and is available for Windows, macOS and Linux. It comes with built-in support for JavaScript, TypeScript and Node.js and has a rich ecosystem of extensions for other languages (such as C++, C#, Java, Python, PHP, Go) and runtimes (such as .NET and Unity).

VSCode

yarn

Yarn is a package manager for your code. It allows you to use and share code with other developers from around the world. Yarn does this quickly, securely, and reliably so you don’t ever have to worry.

Yarn allows you to use other developers’ solutions to different problems, making it easier for you to develop your software. If you have problems, you can report issues or contribute back, and when the problem is fixed, you can use Yarn to keep it all up to date.

e.g. Auto Clean

yarn autoclean
Cleans and removes unnecessary files from package dependencies.

An alternative tool is node-prune, a small tool to prune unnecessary files from ./node_modules, such as markdown, typescript source files, and so on.

This tool is written in go language. And there is also a npm package

npm install -g node-prune

e.g. running this tool

1
2
3
4
$ node-prune
files total 27,330
files removed 3,990
size removed 13 MB

webpack/ gulp/ grunt

These are all build tools. Suggest to use gulp for simple scenarios, and webpack for whole site management.

  • webpack - Packs modules and assets for the browser.
  • gulp - Streaming and fast build system that favors code over config.
  • grunt - Task runner that can perform repetitive tasks like minification, compilation, unit testing, linting, etc.

Web

Web Frameworks

Express

Needless to say, Express is the best Web application framework, providing a robust set of features for building single and multi-page, and hybrid web applications. Your first choice for web development.

Express provides a thin layer of fundamental web application features, without obscuring Node.js features that you know and love.

Restify

A Node.js web service framework optimized for building semantically correct RESTful web services ready for production use at scale. restify optimizes for introspection and performance, and is used in some of the largest Node.js deployments on Earth.

If you only want to write a API website, this is better than Express. And more focus on API.

Common Node.js Modules

underscore/lodash

These are two very useful javascript modules to help extend basic javascript usages. They are very similar, and you can choose one freely.
Underscore and Lo-Dash provide similar functionality. Lo-Dash’s API is a superset of Underscore’s. It provides everything that Underscore does, along with a few additional helper functions. Lo-Dash can generally serve as a drop-in replacement for Underscore with no changes; it works just fine with Backbone.

Lo-Dash answers that with a pretty extensive list on its site, but the claims really boils down to a few things:

  • Usability Improvements
  • Extra Functionality
  • Performance Gains

winston

Multi-transport async logging library. Winston is designed to be a simple and universal logging library with support for multiple transports. A transport is essentially a storage device for your logs.

Use try-catch in javascript

try/catch/throw/finally

Try-catch is a JavaScript language construct that you can use to catch exceptions in synchronous code. Use try-catch, for example, to handle JSON parsing errors as shown below.

  • The try statement lets you test a block of code for errors.
  • The catch statement lets you handle the error.
  • The throw statement lets you create custom errors.
  • The finally statement lets you execute code, after try and catch, regardless of the result.

Use a tool such as JSHint or JSLint to help you find implicit exceptions like reference errors on undefined variables.

Here is an example of using try-catch to handle a potential process-crashing exception. This code try to parse a string into json object.

1
2
3
4
5
6
7
var jsonStr = 'your json object in string';
try {
var jsonObj = JSON.parse(jsonStr);
} catch (e) {
// handle exception
console.error(e);
}

However, try-catch works only for synchronous code. Because the Node platform is primarily asynchronous (particularly in a production environment), try-catch won’t catch a lot of exceptions.

The Error Object

JavaScript has a built in error object that provides error information when an error occurs.

The error object provides two useful properties: name and message.

  • name: Sets or returns an error name
  • message: Sets or returns an error message (a string)

Six different values can be returned by the error name property

  • EvalError: An error has occurred in the eval() function
  • RangeError: A number “out of range” has occurred
  • ReferenceError: An illegal reference has occurred
  • SyntaxError: A syntax error has occurred
  • TypeError: A type error has occurred
  • URIError: An error in encodeURI() has occurred

What is functional programming in javascript

Functional programming produces programs by composing mathematical functions and avoids shared state & mutable data. Lisp (specified in 1958) was among the first languages to support functional programming, and was heavily inspired by lambda calculus. Lisp and many Lisp family languages are still in common use today.

Functional programming is an essential concept in JavaScript (one of the two pillars of JavaScript). Several common functional utilities were added to JavaScript in ES5.

  • Pure functions / function purity.
  • Avoid side-effects.
  • Simple function composition.
  • Examples of functional languages: Lisp, ML, Haskell, Erlang, Clojure, Elm, F Sharp, OCaml, etc…
  • Mention of features that support FP: first-class functions, higher order functions, functions as arguments/values.