Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

An Introduction to Node.js (Part 2)

DZone's Guide to

An Introduction to Node.js (Part 2)

We round out this two-part article by discussing npm, the Node command line tool, and then finish with a quick code along to build a simple application.

· Web Dev Zone
Free Resource

Get deep insight into Node.js applications with real-time metrics, CPU profiling, and heap snapshots with N|Solid from NodeSource. Learn more.

Welcome back! If you missed Part 1 of this Node.js tutorial, check it out here

Environment

To this point, we have seen how Node.js is able to scalably handle a large number of IO tasks, but even with the ingenuity of its architecture, the Node.js stack by itself would not be sufficient to create large-scale applications. In addition, we would need tools to make the development of Node.js applications smooth and simple. In this section, we will explore two of the most important tools; namely, the Node command line tool and NPM.

Node Command Line Tool

The Node command line tool, or node, can be used to execute JavaScript files as well as perform a host of other actions, such as evaluating single lines of JavaScript code, changing the V8 engine options while executing JavaScript, or profiling the execution of a JavaScript file. To download node, see the Node.js Download page. Once node has been installed, we can check its version using the following command:

node -v

Once we are sure that the node has been successfully installed, we can then create a simple JavaScript file named index.js(while index.jsis the standard convention used, the file can be named any valid file name) to be executed by node:

console.log("Hello, world!");

We can now run this file using the following command:

node index.js

Once the execution completes, we will see the following output:

Hello, world!

Although this appears to be a simple example of how to use node, the abstraction provided by Node.js masks the importance of what we have accomplished: We were able to run JavaScript code outside of a browser. As we will see later (when we construct an HTTP server), this is the first step in establishing our JavaScript-based service. Before proceeding to the implementation of this service, we must look at a very important tool included with node: NPM.

Node Package Manager

Dependency management is one of the foremost concerns of any major project or system: tracking all dependencies, including versions, is a nearly impossible task to manually perform. Whatsmore, when the project is cloned or pulled to a new environment, attempting to find and pull all of the associated dependencies can be a nightmare. Instead, dependency management tools have been created to handle this task for us. In general, there are three major parts to a standard dependency management tool:

  1. Repository: contains packaged dependencies that can be used by an application; the packages contained in the repository have some metadata associated with them, including the unique identifier and version of the package, which can be used to select a specific package and a specific version from the repository.
  2. Dependency specification: a list associated with a project that declares the dependencies it requires, as well as the versions (or range of versions) that can be used for each dependency; some complex dependency management tools will also allow for dependencies to be valid only during a specific scope of the build or deployment process (such as the scope declaration for Maven).
  3. Dependency tool: inspects the dependency specification and obtains the required versions of the dependencies; these packages are downloaded to a well-known location in a project, allowing us to import the packages within the source code files we create.

In the case of Node.js, the repository is located at the NPM official website. Although we will not cover the publication of Node.js modules to the NPM repository, the curious reader can refer to the NPM publication documentation for more information. In order to specify the dependencies contained in our Node.js package, we need to create a package.json file in the same directory as our JavaScript files. In order to ease this process, the npm command line tool includes an easy technique for doing this. Simply change directory to the location that contains the JavaScript file to be packaged (the JavaScript file that requires the use of NPM packages) and execute the following command:

npm init

Using the defaults presented by npm, we obtain a package.json in the current directory (the directory containing the JavaScript files to be packaged) with the following content:

{
  "name": "example-node",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

This package.json is very simple, containing only a handful of required key-value pairs. The nameversion, and description relate to the metadata used to advertise this package for use by other packages, while the main key specifies the main JavaScript file in the package (equivalent to the main function in a Java, C, C++, or Python program). The scripts section contains a list of scripts that npm can execute on our behalf. By default, only a non-working test script is provided. Lastly, the author and license keys specify the author and the legal license associated with the package, respectively.

In order to add a new dependency (include another existing NPM package) in our project, we can use npm to download the module and include this new dependency in our package.json file. For example, if we wish to use the NPM colors module (which allows us to color the text printed to the console), we can execute the following command:

npm install --save colors

This command downloads the color module to a known location, namely node_modules/; the --save flag denotes that we wish to update our package.json file to include the new dependency. If we look at our package.json file, we can see that it has been updated to include the new color dependency with a compatible version of 1.1.2 (note that the exact version value may change depending on when the command is executed):

{
  "name": "example-node",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "colors": "^1.1.2"
  }
}

For more information on the caret notation for version numbers, see the semver NPM documentation. We can now create a new index.jsfile in the current directory and utilize the colors package as follows:

var colors = require('colors');

console.log("Hello, world!".red);

While we can simply execute node index.js to execute our JavaScript code, we can also create a new script in our package.json file to do the same. By convention, we will call this script start:

{
  "name": "example-node",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node index.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "colors": "^1.1.2"
  }
}

With this new script, we can now issue the following command to execute our index.jsfile:

npm start

Once we execute this command, we should see the following output on the command line, with the text of the hello world statement in red:

> node index.js

Hello, world!

Although we have seen that npm can perform some very impressive tasks with ease, we have only scratched the surface on its capabilities. For more information on npm and what it can do, see the official NPM documentation. In the next section, we will move from a simple program to a more useful one: standing up an HTTP server and handing HTTP requests.

A Basic HTTP Server

Creating a basic HTTP server is Node.js is akin to the common Hello, World! program in C or Java and is just as easy to build. To create this server, we first create a new directory to hold our package and initialize the directory as an NPM package:

mkdir nodejs-http-server-example
cd nodejs-http-server-example
npm init

Once the package has been initialized, we can create a new script within the package.json file (as we did above) to execute our main file:

{
  "name": "nodejs-http-server-example",
  ...
  "scripts": {
    ...
    "start": "node index.js"
  },
  ...
}

With the script created, we then need to add a dependency to the httpmodule within our package:

npm install --save http

With the dependency has been included, we can then create our index.jsfile:

const http = require('http');

http.createServer((request, response) => {

    const { method, url } = request;

    response.writeHead(200, {'Content-Type': 'application/json'});
    response.write(`{"message": "Received a ${method} request with context path '${url}'"}`);
    response.end();

}).listen(8080);

console.log("Started server");

Line 1 of this script simply imports the httpmodule that we have installed using npm. Line 3 creates the server and creates the function that will serve as our callback for incoming HTTP requests. It is important to note that the callback requires that we provide parameters for the request and then the response. Lines 4 through 10 constitute the body of our callback, which extracts the HTTP method and URL (the portion of the URL after the hostname and port, known as the context path) of the current HTTP request being handled. We then write a status code of 200(OK) and a Content-Type entry for the response header, followed by our desired response body. We then close out our desired changes to the response on line 9.

On line 11, we then start the server, listening for HTTP requests on port 8080. Finally, on line 13, we log a message to the console stating that the server has started. To execute our JavaScript source file, we issue the following command:

npm start

Once the server starts, we see the following output:

> node index.js

Started server

It is important to note that the Started server output, which was written sequentially after we execute the listen method on the server, was printed before the server received a request. This is because the listen method is a non-blocking method: we simply registered a callback to be executed when HTTP requests are received and then we continued on with the normal execution of our program (which in this case, resulted in Started server being logged to the console).

If we make an HTTP POST request to http://localhost:8080, we receive the following output:

{
    "message": "Received a POST request with context path '/'"
}

If we make another request, this time a GET request to http://localhost:8080/dzone, we receive the following output:

{
    "message": "Received a GET request with context path '/dzone'"
}

While our HTTP server is simplistic in its functionality, we have achieved a great deal in a relatively short period of time. In only minutes and with only 10 lines of JavaScript, we were able to stand up an HTTP server and respond to actual HTTP calls. This example can be expanded much further, incorporating more complex response codes, request and response headers, and a wide variety of other HTTP functionality. The interested reader is encouraged to take a look at the Anatomy of an HTTP Transaction Node.js Guide for more information.

Conclusion

Since its creation in 2009, Node.js has radically changed the landscape of server development, providing a framework and tool suite that facilitates the use of JavaScript for both in-browser client code and server-side code as well. Not only does this allow for reuse between frontend and backend components, Node.js also provides a high-performance means of executing a large number of simultaneous IO tasks, such as HTTP or web socket requests. While Node.js may not unseat the other heavyweights in the realm of server development, it undoubtedly deserves the attention it has earned and is an undeniable asset in the toolbox of any serious web developer.

Further Reading

For more information on Node.js, see the following sources:

Node.js application metrics sent directly to any statsd-compliant system. Get N|Solid

Topics:
web dev ,node.js ,npm ,command line tools ,backend

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}