It is estimated that virtually every website in the world uses JS, and since the creation of Node.js, millions of systems have been running server-side JS.
This article will explain what Node.js is, how popular it has become, and when development teams should consider using it.
In 2009, Ryan Dahl wrote the first version of Node.js to create an alternative to the Apache Server while also offering a better model for handling requests in a non-blocking way that would improve how the servers handle multiple simultaneous connections.
The key design aspect of Node.js is that it performs non-blocking asynchronous I/O. An Input/Output operation can be anything that is not pure computation, for example, writing a file to disk, opening a connection to a database, or making a request to an external API.
Most online platforms are not CPU-intensive; they are data-intensive or I/O-intensive. They query databases and reply with processed data. In a multi-threaded server environment, at any given time, typically, there will be multiple threads that are blocked, waiting for an external data source to reply (whether it is a database, a persistence backend, or an external API). This means most server resources are locked and wasted by threads that aren't doing much.
On the other hand, Node.js is single-threaded and blocks on any CPU-bound operation, but it is multi-threaded and asynchronous for any I/O operation. As soon as the code makes an I/O request, this is delegated to the underlying asynchronous library libuv, and the event loop is free to continue its work. This allows Node.js servers to handle thousands of concurrent connections with a considerably small CPU footprint.
Because of the asynchronous nature of Node.js, developers need to have a good grasp on working with callbacks and promises. The good thing is that the typical user code of Node.js does not need to handle threads, which is a common source of bugs in languages that facilitate this (like C++ or Java).
One of the typical sources of software development costs is the need to use different languages for backend, Frontend, and data manipulation. For example, a given platform could have its backend written in Java, its Frontend in PHP with a templating engine, use a relational database like MySQL for data storage and manipulation, and connect different modules via XML-based messaging. This means each layer of the architecture uses a foreign language, which adds complexity and causes the need to hire developers for each different technology.
Popular Node.js frameworks
Sails.js is an MVC (Model-View-Controller) application framework for node.js. Bundled with an ORM, it allows using any database. REST APIs and single-page apps (SPA) are auto-generated, with "blueprints" available to jumpstart development. Sails.js was inspired by Ruby-on-Rails "convention over configuration" and "scaffolding" principles. Sails.js intensively relies on code generation, which may not be appropriate for all scenarios. It offers native WebSockets support, among other modern features.
Express presents itself as a "Fast, unopinionated, minimalist web framework for Node.js." It's one of the most popular app frameworks for Node.js out there. Express uses the "Chain of Responsibility" design pattern, using "middleware" functions that handle incoming HTTP requests. Many frameworks are, in fact, based on Express.js. Examples are Sails, Nest, and Kraken, among many others.
Express offers a minimal interface for building applications, adding Node.js the capability of dealing with routes and endpoints with little to no complexity.
Its name derives from HTTP + API; Hapi is a simple and secure framework for building Node.js apps. Developed initially by Walmart to handle the massive amount of requests they received on Black Friday, its trademarks are scalability and security. Hapi core does not have any external code dependencies. Their development team enforces a lot of security best practices. Hapi was created by Eran Hammer, a known identity protocols author.
Because one of the main drivers of Hapi is security, they offer a set of official plugins so developers can avoid resorting to unverified npm libraries. Another security-related strong point is that Hapi natively integrates an authorization and authentication architecture.
Socket.io is a server-side library for WebSockets. If a WebSocket connection is unavailable, it will default to long-polling via HTTP, making it a reliable component for handling connections to the browser. Its features include "room" namespaces, multiplexing, binary buffers, etc. Interestingly, they offer client libraries for many other popular programming languages like Java, Python, and C++.
A very popular templating engine, Pug allows rendering dynamic content server-side. Pug seamlessly integrates with Express.js, as stated in this guide. It is inspired by HAML, another popular DRY ("Don't repeat yourself") templating library.
As a side note on server-side generated HTML pages, it may not always be the best architectural choice. Sometimes statically exporting pages to be served by CDN and keeping all dynamic code browser-side can positively impact scalability.
Nodemon is a utility for development that monitors the code for changes and automatically reloads as needed. More than 1.5 million projects use Nodemon worldwide.
When to use Node.js
Given Node.js asynchronous I/O nature, it is an excellent choice for I/O bound apps like REST APIs that gather information from databases and external sources. Data Streaming apps, any Data-Intensive application, JSON APIs and web services, and servers for Single Page Apps.
Under the hood, a key component of Node.js is the cross-platform asynchronous I/O library "libuv." This library is written in C language, and as they state on their website, "Node is libuv with a very well known client language." Its cross-platform nature allows each operating system to resolve the implementation of asynchronous I/O how it suits best, currently being supported in Windows, Linux and macOS.
One of the most popular application frameworks for Node.js is Express, allowing the development of minimalistic REST APIs by concatenating "middleware" functions in endpoint declarations.