Lead Image © lightwise 123rf.com

Lead Image © lightwise 123rf.com

Programming with Node.js and JavaScript

Turbulent World

Article from ADMIN 20/2014
By
Web application development is becoming increasingly complex, and the number of libraries and frameworks available for the job can be overwhelming. We take a look at the popular JavaScript-based Node.js.

In web development, trends quickly come and go. For a time, Ruby on Rails was all the rage; now the hype has shifted away from the framework and is focused on JavaScript, the only programming language to run on the client and on the server, if you subscribe to the credo of JavaScript's followers.

Server-side JavaScript frameworks have been around for a while, such as Helma [1], on which the website of the Austrian Broadcasting Corporation (ORF) is based. Helma is slowly being mothballed, but a successor named Ringo is already in the starting blocks. Projects like these, however, have only ever been niche products compared with Rails and PHP frameworks.

The situation is different with the Node.js platform (or Node for short) [2], which has been extremely popular for several years and has attracted a large community of developers. Node was developed by Ryan Dahl, who coupled Google's V8 JavaScript compiler with some non-blocking C libraries whose functions are available in JavaScript. This approach allows event-based processing of work requests and, thus, more concurrent requests than the Apache server can handle – although Apache also has an event-based processing module [3] in its more recent incarnations.

Spoiled for Choice

One of the strengths of Node.js, and a result of its massive popularity, is the huge number of modules that extend its functionality. The hype now goes so far that Node is no longer limited to web applications but is even used for classic system tools. Thus, the administration tools in SmartOS [4] are based on Node – which is perhaps less surprising if you know that Joyent, the company behind SmartOS, is involved in the Node project and sees itself as the "steward" of the project. Even Microsoft has released a tool that is based on Node [5] for managing the Azure cloud via the Linux and OS X command line.

Installing Node is pretty simple. Most Linux distributions now have it in their repositories, although you will rarely find this to be a current version. It is better to download the source code, unpack, and then run make and make install to build and install the program. You need various development packages in place for this, such as Libev. For Ubuntu, current Node versions exist in the ppa:chris-lea/node.js repository.

After the install, you will find two executables, node and npm, on your hard drive, typically in the /usr/local/bin directory. The modules are stored by default in /usr/local/lib/node_modules/. Besides Linux, Node runs on OS X, (Open)Solaris, and Windows.

As indicated, Node is primarily a JavaScript compiler/interpreter with additional libraries. If you launch node at the command line, you are taken to a prompt where you can enter JavaScript commands and functions:

> "admin".toUpperCase()
'ADMIN'

Programmers typically work with Node just as with any other scripting language: You write your code in a file and execute it with node. Because Node reveals its capabilities especially as a web framework, the classic Hello World example is a small web server that is programmed in a few lines. The http needed for this module is loaded in typical JavaScript style using require and is bound to a normal variable:

var http = require('http');

The createServer function of the http module expects a function that is executed when a request event occurs. In Listing 1, this takes the form of an anonymous function with one parameter for the request and one for the response to the client. In the function body, the writeHead function first writes the header and then expects the response code and an optional hash for the headers. The end function usually stipulates the end of the header and body, which is provided by the write function. In this case, end does everything in one fell swoop if you pass in the payload data to it.

Listing 1

Simple Web Server

01 var http = require('http');
02 http.createServer(function (req, res) {
03    res.writeHead(200, {'Content-Type': 'text/plain'});
04    res.end('Hello from Node.js\n');
05 }).listen(3000, '127.0.0.1');

Suppose the code in this example resides in a file named server.js; in this case, a call to node server.js launches the server on port 3000. On this basis, you could start to build your own web server by incorporating case distinctions into the request method that jump to other functions depending on the URL. This process is quite a chore, so Node users have posted several modules that simplify URL routing. The most popular is Express [6], which is used in most web applications and offers even more practical capabilities. An alternative would be Director from the Flatiron project, for example.

Node Packages

External modules are installed using the NPM package manager, which is included in the Node distribution. You can install a package manually with a call to npm install module. The modules end up in the node_modules subdirectory below the current directory. System global Node modules are installed with -g, but this technique is usually frowned upon unless you are installing a module that contains an executable command.

The idea is that each Node application can work with exactly those versions of the modules that it needs, which are not necessarily identical to those of another Node application. If you use require to integrate a module into a Node application, Node examines not only the current directory but also all higher levels, up to the root directory. This means you could also maintain a repository of Node modules available to multiple applications if desired.

After installing the Express module by typing npm install express (Figure 1), you integrate in the normal way using var express = require('express'). Listing 2 shows how to structure your web application with Express. An Express application is generated by calling the express() function, which acts as a switching point from then on. Routing takes place in line 11. A link between the URL and the calling function is created by calling the Express method with the same name as the required HTTP method.

Listing 2

Express Web Server

01 var http = require('http'),
02     express = require('express');
03
04 function root(req, res) {
05    res.end("hello");
06 }
07
08 var app = express();
09 app.set('port', process.env.PORT || 3000);
10
11 app.get('/', root);
12
13 var server = http.createServer(app);
14 server.listen(app.get('port'), function() {
15    console.log('Express server listening on port ' + app.get('port'));
16 });
Figure 1: Installing the Express module automatically adds a variety of other packages.

In the example, the call to app.get() means that when the / URL is called by HTTP GET, the root function is executed. To assign an action to a HTTP POST request for the same address, you would use app.post() instead.

Again, the server runs on port 3000 if you launched the program by typing node app.js, for example. If you then use your web browser to access http://servername:3000 , you will see the Hello World message.

Templates

Outputting HTML in such a primitive way also works, of course, but far better ways are available, namely templates. Node and Express also offer a variety of template engines that you can use to define the page layout, which is filled with content at run time. The Jade templates, for example, which completely do without angle brackets and closing tags  – instead using the indent level for structuring  – are extremely compact. A Jade template can thus look like this:

html(lang="en")
  body
  h1 Hello

As you can see, this approach saves a huge amount of typing. Node converts the Jade code to HTML in real time when you call the render function of the response object with the template file as its first parameter. Express refers to the suffix to determine the template engine. If it is missing, Express uses the default engine, which defines a call to app.set('view engine', 'jade'). If you don't want to learn yet another language, in the form of Jade, you can use, for example, Swig for a template syntax that enriches classic HTML with variables [7]. By default, Express applications look for templates in the views subdirectory. If you want to define a different location, you can do so with app.set('views', directory). The global __dirname variable of a JavaScript Node file is useful here. It contains the directory in which the file is located.

Of course, templates only become really interesting if you also pass variables to them; otherwise, you could write static HTML files. In Swig templates, variables are enclosed in curly brackets on the left and right. Filters, loops, functions, and template inheritance can also be used. The latter is interesting if you want to outsource, for example, the HTML header or visible footer of a page to a single file and then use it on all your pages.

To transfer the variables from the Node code to the template, you pass them in as JavaScript objects. The corresponding code is shown in Listing 3. If this looks strange, remember that the first occurrence of firstname is the keyname of the object, whereas the second is the JavaScript variable of the same name. In the Swig template, {{firstname}} outputs the corresponding variable.

Listing 3

Template Rendering

01 var firstname = "John";
02 var lastname = "Doe";
03 app.get('/', function(req, res){
04   res.render('index.html', { firstname: firstname, lastname: lastname });
05 });

The data in Node applications usually originate from NoSQL databases, such as MongoDB, for which matching NPM modules exist. However, classic relational databases such as MySQL, MariaDB, and PostgreSQL are also supported. If you look around on the web, you will continually find interesting projects that depart from the familiar framework. An example is Bookshelf, which is an object-relational layer for MySQL, PostgreSQL, and SQLite that supports transactions and JavaScript. It promises to provide an unusual but powerful programming model for asynchronous processing of requests and queries.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy ADMIN Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • CoffeeScript: A Replacement for JavaScript?

    Through the years, many languages have tried to improve or even replace JavaScript, including CoffeeScript, which runs in all JavaScript Runtime Environments and compiles into JavaScript.

  • Workflow-based data analysis with KNIME
    They say data is "the new oil," but all that data you collect is only valuable if it leads to new insights. An open source analysis tool called KNIME lets you analyze data through graphical workflows – without the need for programming or complex spreadsheet manipulation.
  • Modularize websites with Web Components
    Web Components let you define your own HTML tags to restructure monolithic web pages into smaller services and simplify maintenance and servicing.
  • A self-healing VM system
    The right combination of mostly free automation and monitoring tools can create a self-healing system, in which your servers fix themselves.
  • HPC fundamentals
    The pdsh parallel shell is a fundamental HPC tool that lets you run a command across multiple nodes in a cluster.
comments powered by Disqus