Setting Up Node.js to Serve Web Applications
This article is a simple yet effective introduction to getting started with Node.js, which is often described as an asynchronous server-side JavaScript library written in the C language. To server-side OO developers, this may be a bit confusing. After all, how can JavaScript be a server-side implementation? It can’t; but Node allows the JavaScript V8 engine (written by Google) to run on a server-side platform, thus allowing you to deploy Node apps to the cloud (i.e., using Microsoft Azure).
One of the main reasons to use Node for a hosted platform is for performance. Unlike traditional application hosting platforms, such as the Apache Web server that uses a single thread to handle a separate request, Node uses an event-loop model for handling incoming application requests. The traditional single-thread-per-request model ends up increasing a processor’s I/O wait time by using multiple threads (one for each request).
The event-loop model used by Node decreases the I/O wait time by issuing an event that tells the processor when a request has finished processing using function callbacks of a Node application, thus using a single thread to handle multiple requests. If this seems a bit confusing at first, you can learn more about the event-loop model at http://nodejs.org/about/. The main thing to take away is that Node uses a single thread to handle all application requests, whereas more traditional servers such as Apache, IIS, and others use a separate thread for each request.
To install Node, visit http://nodejs.org and click the Install button, which detects the operating system you are using to install the right package. To verify that Node is installed, open a command window, type node –version, and see the result.
To start using Node, type node at the command prompt and start typing in JavaScript. You will often put your Node application code into a .js file that is executed either from the command prompt or by using an IDE such as Eclipse.
Setting Up a Node HTTP Server
One of the most common uses for Node is as a web server for applications created with AngularJS or Express.js.
The following code sets up a simple server:
var http = require('http'); var server = http.createServer(function onRequest(request, response) { response.writeHead(200, { 'Content-Type': 'text/plain'}); response.write('Welcome to a simple HTTP Server'); response.end(); }).listen(3000);
The first line includes the HTTP module. Like other frameworks, Node includes a set of built-in modules that perform certain tasks. You can think of a module like a namespace in .NET or a package in Java.
The require statement imports the module. Next, the server instance is created using the createServer function. If you are a Java programmer, the syntax may look very similar to setting up a Java servlet. A callback function containing the request and response objects is passed in as a parameter to the main function.
Finally, we create a simple header and write out some content to the stream. After running it from your IDE or node command line, the server should start. As indicated by a blinking cursor at the command prompt, the server is waiting for requests. If you open your browser and go to localhost:3000, you should see the welcome message displayed from the previous example.
So how do you load application pages using a Node server? To do this, you can use the http, fs, path, and url modules. (The fs module is the file system module and is responsible for streaming files to Node.)
Here is an example for loading pages:
var http = require('http'); var fs = require('fs'); var path = require('path'); var url = require('url'); var server = http.createServer(function onRequest(request, response) { var urlParts = url.parse(request.url); var page = 'pages' + urlParts.pathname; fs.exists(page, function fileExists(exists) { if (exists) { response.writeHead(200, { 'Content-Type': 'text/plain'}); fs.createReadStream(page).pipe(response); } else { response.write('Page Not Found'); response.end(); } }); }).listen(3000);
In the preceding example, another callback function is used to see whether the page exists. If it does, we pipe the file contents to the browser; otherwise, we send a message saying the page cannot be found. You can use the previous code for most of your application hosting needs if your application is simple and does not use an application architecture such as MVC.
If your application is a large one, the previous code has to be repeated in different ways for handling different paths, and so on. Node helps solve this problem with a concept referred to as connect middleware (CM).
If you come from a Java or .NET background, you can think of CM as a filter. Like filters, CM is some code that plugs into the request pipeline to perform certain functions. Some examples of CM are for logging and authentication. It is built on top of Node’s HTTP server and is referenced through the package module name connect in the application.
To add CM to your Node modules, go to a command prompt and type npm connect.
The following code is an example of CM in use:
var connect = require('connect') , http = require('http'); var app = connect() .use(function(req, res){ res.end('Hello from Connect!\n'); }); http.createServer(app).listen(3000);
From this example, you can see that the app variable is passed into the createServer function, which adds all the CM functionality.
Here is another way to write the code using CM but with a bit more flexibility:
var connect = require('connect'); var intercept = function(request,response,next){ console.log("hello"); next(); }; var server = connect() .use(intercept) .use(function onRequest(request, response) { response.write("Hello from the Connect Middleware Package"); response.end(); }).listen(3000);
This example differs from the previous example because we created a function called intercept that handles the request and response, but also passes in a parameter called next.
Then we set up the server using the connect package and tell it to first use the intercept function before handling requests (similar to the other examples using just the http module).
If you write something to the console in the intercept function, it displays in the console before the Hello from the message appears in the browser. You can see how you can more effectively write your code to handle multiple operations by using this example.