Third party modules and Express JS

Now that we have built a router of our own and understand the basics of Node.js, it is time to get introduced to one of the most widely-used frameworks for Node.js, Express (http://expressjs.com). Node.js provides the infrastructural components to build a web application, but there is too much stuff to handle. Therein lies the role of the web frameworks. There are quite a few web frameworks that provide a higher level of abstraction for building applications on Node. You can see a list of most of them here:

https://github.com/joyent/node/wiki/Modules#wiki-web-frameworks-full

Express is a web application framework for Node, built over the Connect middleware, that provides many more helpers and structural aspects to build our web applications.

To get started with the Express framework, we need to install it using npm, the Node.js package manager.

sudo npm install -g express

The previous command will install Express as a global (-g) module and make express available as a command. Let us create an Express app:

express hello-express

This will create a folder called hello-express with certain files and folders in it. Let us see and understand these files.

The first file to understand is package.json. This is the file that defines a Node.js application package. It has the application metadata such as the name, description, and version. More importantly, it has the module dependencies listed. The dependency list is used by npm to download the required modules.

{
  "name": "application-name",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app"
  },
  "dependencies": {
    "express": "3.1.0",
    "jade": "*"
  }
}

The most important things in your package.json are the name and version fields. These fields are required, and together, they form a unique identifier for a particular release of the package. To begin with, let us change the name of our package to hello-express. The version field consists of the following (in the same order):

  • A number (major version)
  • A period
  • A number (minor version)
  • A period
  • A number (patch version)
  • Optional: a hyphen, followed by a number (build)
  • Optional: a collection of pretty much any non-whitespace characters (tag)

If we set private to true, npm will not publish it to a repository. This ensures that you don't end up publishing your code to a public repository by mistake.

The scripts object has a mapping of commands to those points in the application lifecycle at which they should be run. In this package, we are telling Node.js that it should run the node app command when the application is started with npm. There are some predefined lifecycle commands, such as start, stop, restart, and test, which can be run using npm <command> like npm start.

You can also run arbitrary commands using run-script. For this, you add the command to the scripts object and then run it as npm run-script <command>.

And finally—the most interesting part of the package that brings in the magic—dependencies. This object is a mapping of the name and version of your dependency packages and will be used by npm to pull in all the required dependencies.

In our package, express has already defined the dependency on Express and Jade. To pull in these dependencies, run the following command:

npm install

The output will list all the dependencies it downloaded.

[email protected] node_modules/jade

├── [email protected]

└── [email protected]

[email protected] node_modules/express

├── [email protected]

├── [email protected]

├── [email protected]

├── [email protected]

├── [email protected]

├── [email protected]

├── [email protected]

├── [email protected]

├── [email protected] ([email protected])

└── [email protected] ([email protected], [email protected], [email protected], [email protected])

The dependencies will be placed in a folder called node_modules.

Next, we will take a look at the application file app.js:

var express = require('express')
  , routes = require('./routes')
  , http = require('http')
  , path = require('path'),

var app = express();

app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views'),
  app.set('view engine', 'jade'),
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(path.join(__dirname, 'public')));
});

app.configure('development', function(){
  app.use(express.errorHandler());
});

app.get('/', routes.index);

http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});

In the first few lines, Node.js loads the modules required for us to work with. We are already familiar with http and path. The express module brings in the Express framework. And one more module that we are loading in is ./routes, which will load the module defined in the local routes folder, defined by ./routes/index.js. The following code snippet focuses on the first few lines of the previous code snippet:

var express = require('express')
  , routes = require('./routes')
  , http = require('http')
  , path = require('path'),

In the next line, it instantiates the Express framework as an app:

var app = express();

Then comes the application configuration:

app.configure(function(){

});

In the previous few lines, we are defining a function that will configure the app. The signature for app.configure is app.configure([env], callback), where env is the runtime environment variable or the production environment variable, as is defined by process.env.NODE_ENV. When we don't specify env, it will be set for all environments.

The following settings have been provided to alter how Express behaves:

  • env: Environment mode, defaults to process.env.NODE_ENV or "development"
  • trust proxy: Enables reverse proxy support, disabled by default
  • jsonp callback: Enables JSONP callback support, enabled by default
  • jsonp callback name: Changes the default callback name of ?callback=
  • json replacer: JSON replacer callback, null by default
  • json spaces: JSON response spaces for formatting; defaults to 2 in development, 0 in production
  • case sensitive routing: Enables case sensitivity, disabled by default, treating /Foo and /foo as the same
  • strict routing: Enables strict routing, by default /foo and /foo/ are treated the same by the router
  • view cache: Enables view template compilation caching, enabled in production by default
  • view engine: The default engine extension to use when omitted
  • views: The view directory path

The following code snippet demonstrates how to assign settings to an application:

  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views'),
  app.set('view engine', 'jade'),

The settings used by the application here are port, views, and view engine, specifying that the application should run on port 3000, the views will be placed in the views folder, and the engine to be used is Jade. We will see more about views later. Certain features can also be specified, as shown in the following snippet:

  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(path.join(__dirname, 'public')));

As Express builds over Connect middleware, it brings in a lot of existing functionality from Connect. Connect's use method configures the app to utilize the given middleware handle for the given route, where the route defaults to /. You can see the list of middleware provided by Connect at http://www.senchalabs.org/connect/.

Let us walk through the middleware components being used here. The Favicon middleware will serve the favicon for the application. The Logger middleware logs requests in a custom format.

The Body parser parses the request bodies supporting different formats; this includes application/json, application/x-www-form-urlencoded, and multipart/form-data.

Method Override enables the faux HTTP method support. This means that if we would like to stimulate the DELETE and PUT method calls to our application, we can do it by adding a _method parameter to the request.

app.router provides an enhanced version of Connect's router module. Basically, this is the component that determines what to do when we use routing methods like app.get. The last middleware, Static, provides a static file server and configures it, serving files from the public directory.

For the development environment, the following two lines of code show how to set up the Error handler middleware so as to provide stack traces and error messages in the responses.

app.configure('development', function(){
  app.use(express.errorHandler());
});

The next line configures the router to route / to be handled by the index method in the routes module:

app.get('/', routes.index);

At the end, we start the HTTP server configured to use the app instance that we just configured.

http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});

In the configuration of the app, we saw some folders coming into play, namely, routes, views, and public.

routes is a module that we will be writing all our handlers to. In the case of /, we have mapped it to serve from the index method, using the routes.index method. If you open routes/index.js, you will see that index is a method exposed from this module.

exports.index = function(req, res){
  res.render('index', { title: 'Express' });
};

This function signature is similar to the handlers we wrote. It is a function that takes a request and response as parameters. Here we are using the Express method response.render, which will render the mentioned view using the second parameter as the model or data.

The views are present in the views folder and use the Jade (http://jade-lang.com/) view engine. Jade is a high-performance template engine, heavily influencedby Haml (http://haml.info/), and implemented with JavaScript for Node.js. Like many modern HTML generation engines, Jade tries to make the UI code easier, cleaner, and simpler, getting rid of the inline code and the HTML tags noise.

We will now see the views defined in our Express app. There are two files to see here: layout.jade and index.jade.

layout.jade, as the name suggests, is the template for the layout that will be used by the different pages in our application. It may be used to place the common code of the skeleton for the pages in our application, which is shown in the following snippet:

doctype 5
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/style.css')
  body
    block content

In Jade, we don't need the start and end tags because it identifies the start and end of the tags by the indented blocks. So when we render this Jade file, it will generate the following HTML code:

<!DOCTYPE html>
<html>
  <head>
    <title>{TITLE}</title>
    <link rel="stylesheet" href="/stylesheets/style.css" />
  </head>
  <body>{CONTENT}</body>
</html>

In the previous piece of code, two things are left undefined, {TITLE} and {CONTENT}. In the Jade template, we define the title as follows:

    title= title

We tell Jade to use the title from the data passed to render as title. The second thing, {CONTENT}, is defined as block in Jade.

    block content

block content is a plugin point provided in the layout template, which can be described by any template extending from it.

index.jade inherits from layout.jade. In our index handler, we render the index view using the data {title: 'Express'}. Take a look at the following code snippet:

extends layout
block content
  h1= title
  p Welcome to #{title}

In the previous file, we define the content block to have a h1 and p tags. So, with the given input and because it extends the layout, the Jade engine will generate the following HTML:

<!DOCTYPE html>
<html>
  <head>
    <title>Express</title>
    <link rel="stylesheet" href="/stylesheets/style.css" />
  </head>
  <body>
    <h1>Express</h1>
    <p>Welcome to Express</p>
  </body>
</html>

We will see more functionality and syntax in Jade as we work on our chat application in the next chapter.

In the HTML code generated, we can see that /stylesheets/style.css is being referred to; this file is served by the static file server we configured in the app. We can find this and the other files in the public folder.

To run this application, we will use npm. Run the following command on the console:

npm start

Then go to http://localhost:3000/.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset