/ Node

An Introduction to Node.js

Node.js is the platform that, in a very short time, has reached such worldwide success that today it is one of the most interesting platforms for writing web applications and more. In essence, Node is an open source and cross platform runtime environment for running JavaScript code. It is widely used to build back-end services, or APIs that power various services and client applications. In practice client apps are just a surface, it requires a backed running on a server to send messages, store data, send emails, kickoff workflows, etc.

It is great for prototyping and agile development as it enables us to write applications faster, with fewer lines of code, fewer number of files. Not only this, the applications are faster and can handle more requests. Node is extensively used by companies like Walmart, Uber, Netflix, PayPal, Yahoo to name a few.

Here are a few other features or benefits of using Node.js

  • It uses JavaScript
  • Overall code base is clean and consistent as JS is used both on the front-end and the back-end
  • One of the largest ecosystem of open source libraries, allowing the developer to focus only on the core of the product being built
  • Non-blocking asynchronous architecture by default (explained later)

Origins of Node

As evident by the name Node.js, it is clear that Node uses JavaScript. Previously the only place you could run JavaScript code is your browser, it is made possible by a JS engine that resides with your browser. Every browser has a different JS engine, the one we are interested is the Google's open source Chrome v8 Engine, which is by far the best performing JS engine.

In 2009, Ryan Dahl took the v8 engine and embedded it in a C++ program and called it Node. Around it the C++ program essentially wrapped an environment with some specific system variables and objects, which will be covered in future blogs. It did not have the document object as you would expect with JavaScript, but it was packed with additional modules that gave it capabilities which were not available with a browser, for example fs.readFile() allowing us to access the file system, creating an http server using http.createServer(), etc.

Node.js was born in 2009 from an idea of Ryan Dahl, who was searching for a way to track the time needed to upload a file from a browser without continuously asking the server “how much of the file is uploaded?” His idea was to explore what would happen if the requests were non-blocking, and JavaScript seemed the perfect language for two main reasons: at the time, it didn’t have an I/O library, and the async pattern, which is very useful for writing non-blocking applications, was already present in the language.

So, the important takeaway is that, Node is not a programming language, it is a runtime environment for executing JavaScript Code that helps develop highly scalable, data intensive and real time applications.

Now the question that arrives is what makes all of this possible? The simple answer is Asynchronous nature of Node.

Understanding Asynchronous

Suppose we have a thread that serves a database request, now if you're programming with something like ASP or Rails which is synchronous by default, that thread can only serve on request at a time. So whenever a request arrives, the thread has to wait till it gets to result and then can handle other requests. So to handle another request meanwhile, we need to start another thread. Now imagine having too many request, you will soon run out of threads and other clients have to wait, or we will need more hardware. This is the problem with synchronous style of programs.

Node by default is asynchronous, here a single thread can handle multiple requests. When it receives, say, a database request, it can handle that request, it doesn't wait for the results but goes on to handle the other requests that arrived in the mean time, all of this while the database processes the request, and when the result is ready, the database notifies Node about it.

Node Under the Hood

Now we know that node is asynchronous, i.e. a single thread can handle multiple requests, this makes Node applications highly scalable.

In the previous example, we mentioned that the database notifies Node when a result for a request is ready. In practice, this is done by putting a message to an event queue. Node continuously monitors the queue in the background and when it finds an event, it takes it out and processes it. This makes it great for I/O Intensive apps.

Note: Node Should not be used for CPU intensive applications, like Video encoding or image manipulation, etc, (more calculation, less interaction with FS) Since for node applications many clients can potentially interact a single thread , if it’s given a CPU intensive task, the other client will have to wait, while it processes the request/task.

Node Hello World

Installing Node is pretty simple, just download the latest LTS version from nodejs.org. Alternatively on Ubuntu use the command apt-get install nodejs npm or brew install node on MacOS (You need to install Homebrew first)

After this just type node --version to check if node is installed properly, at the time of writing this, the latest version was 8.11.4, you can expect a similar output

Now simply create a file app.js

function sayHello(name){
	console.log("Hello " + name);
}
sayHello("Tom");

You can run this by using the command node app.js and you'll get the following output:

$ node app.js 
Hello Tom

And that's about it, now let's learn about more about the Node architecture.

Node Module System

Modules are the fundamental building blocks of the code structure. To keep the basic implementation of Node as streamlined as possible, rather than incorporating every component in Node itself, developers add functionality by means of modules. The module system allows you to organize your code, hide information and only expose the public interface of a component.

So to use these modules in our app, we use the require() call. On the other side, when developing a module we use module.exports to make it available to import.

There are some core modules that are a part of Node that are compiled into the binary. The core modules are defined within Node.js's source and are located in the lib/ folder. Just like any other module, we can load it by passing the identifier to require(). For instance, require('http') will always return the built in HTTP module, even if there is a file by that name. Some of the core modules are os, fs and event amongst others.

Core Modules in Node.js

The module loading mechanism in Node.js is caching the modules on the first require call. It means that every time you use require('awesome-module') you will get the same instance of awesome-module, which ensures that the modules are singleton-like and have the same state across your application.

The module dealing with module loading in the Node core is called module.js, and can be found in lib/module.js in the Node.js repository.

Node Global Object

While in browsers the global scope is the window object, in Node the global scope of a module is the module itself, so when you define a variable in the global scope of your Node module, it will be local to this module.

In browsers, the top-level scope is the global scope. That means that in browsers if you're in the global scope var something will define a global variable. In Node.js this is different. The top-level scope is not the global scope; var something inside an Node.js module will be local to that module.
NodeJS Documentation

Each JS file is treated as a module. Node automatically wraps the code of a JS file in a self IIFE with exports, require, module, __filename, __dirname as parameters to the function. IIFE is a Immediately-Invoked Function Expression it executes immediately after it's created, and entire script block is parsed before any code in it is executed. This makes these objects available to each module by default.

The objects listed above are specific to Node.js. There are a number of built-in objects that are part of the JavaScript language itself, which are also globally accessible.

Node.js Framework and Tools

Node.js is a low-level platform, and to make things easier and more interesting for developers thousands of libraries were built upon Node.js. Many of those established over time as popular options. Here is a non-comprehensive list to the ones considered very relevant and worth learning:

  • Express: Express is to Node what Rails is to Ruby. It is a light-weight web application framework to help organize your web application into an MVC architecture on the server side.
  • Meteor, an incredibly powerful full-stack framework, powering you with an isomorphic approach to building apps with JavaScript, sharing code on the client and the server. Once an off-the-shelf tool that provided everything, now integrates with frontend libs React, Vue and Angular. Can be used to create mobile apps as well.
  • koa, built by the same team behind Express, aims to be even simpler and smaller, building on top of years of knowledge. The new project born out of the need to create incompatible changes without disrupting the existing community.
  • Next.js, a framework to render server-side rendered React applications.
  • Socket.io, a real-time communication engine to build network applications.