Getting started

First, if you have not already done so, download and install Node. Then, to start your first application, create a directory on your machine:

$ mkdir hello-world

In this same directory you'll be defining the application "package", which is the same as any other Node package. You'll need a package.json file in the directory, with express as a dependency.

{
  "name": "hello-world",
  "description": "hello world test app",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "express": "4.x"
  }
}

In general, as a best practice, use npm info express version to determine the latest version of Express, and then use the version number returned instead of "4.x" to prevent future surprises.

Now that you have a package.json file in this directory use npm to install the dependencies, in this case just Express:

$ npm install

Once npm finishes you'll have a localized Express dependency in the ./node_modules directory. Verify this with npm ls as shown in the following snippet displaying a tree of Express and its dependencies.

$ npm ls
hello-world@0.0.1 /private/tmp
└─┬ express@3.0.0beta7
  ├── commander@0.6.1
  ├─┬ connect@2.3.9
  │ ├── bytes@0.1.0
  │ ├── cookie@0.0.4
  │ ├── crc@0.2.0
  │ ├── formidable@1.0.11
  │ └── qs@0.4.2
  ├── cookie@0.0.3
  ├── debug@0.7.0
  ├── fresh@0.1.0
  ├── methods@0.0.1
  ├── mkdirp@0.3.3
  ├── range-parser@0.0.4
  ├─┬ response-send@0.0.1
  │ └── crc@0.2.0
  └─┬ send@0.0.3
    └── mime@1.2.6
    

Now to create the application itself! Create a file named app.js or server.js, whichever you prefer, require Express and then create a new application with express():

var express = require('express');
var app = express();

With the new application instance you can start defining routes via app.VERB(), in this case "GET /" responding with the "Hello World" string. The req and res are the exact same objects that node provides to you, thus you may invoke req.pipe(), req.on('data', callback) and anything else you would do without Express involved.

Express augments these objects to provide you with higher level methods (such as res.send(), which, among other things, adds the Content-Length for you):

app.get('/hello.txt', function(req, res){
  res.send('Hello World');
});

Now, to bind and listen for connections, invoke the app.listen() method. It accepts the same arguments as node's net.Server#listen():

var server = app.listen(3000, function() {
    console.log('Listening on port %d', server.address().port);
});

Using template engines with Express

Before Express can render template files, the following application settings have to be set.

Then install the corresponding template engine npm package.

$ npm install jade --save

Express-compliant template engines such as Jade, export a function named __express(filePath, options, callback), which is called by res.render() to render the template code.

Some template engines do not follow this convention, the Consolidate.js library was created to map all of node's popular template engines to follow this convention, thus allowing them to work seamlessly within Express.

Once the view engine is set, you don't have to explicitly specify the engine or load the template engine module in your app, Express loads it internally as shown below, for the example above.

app.engine('jade', require('jade').__express);

Create a Jade template files named "index.jade" in the views directory, with the following content.

html
  head
    title!= title
  body
    h1!= message
    

Then create a route to render the "index.jade" file.

app.get('/', function (req, res) {
  res.render('index', { title: 'Hey', message: 'Hello there!'});
})

On making a request to the home page, "index.jade" will be rendered as HTML.

To better understand how template engines work in Express, read "How do I create custom template engines in Express?".

Using express(1) to generate an app

The Express team maintains a handy quickstart project generator, aptly named express(1). If you install express-generator globally with npm, you'll have it available from anywhere on your machine:

$ npm install -g express-generator

This tool provides a simple way to get an application skeleton going, but has limited scope, for example it supports only a few template engines, whereas Express itself supports virtually any template engine built for node. Be sure to check out the --help:

Usage: express [options]

Options:

  -h, --help          output usage information
  -V, --version       output the version number
  -e, --ejs           add ejs engine support (defaults to jade)
  -H, --hogan         add hogan.js engine support
  -c, --css   add stylesheet  support (less|stylus|compass) (defaults to plain css)
  -f, --force         force on non-empty directory
  

To generate an application with Jade and Stylus support:

$ express --css stylus myapp

create : myapp
create : myapp/package.json
create : myapp/app.js
create : myapp/public
create : myapp/public/javascripts
create : myapp/public/images
create : myapp/public/stylesheets
create : myapp/public/stylesheets/style.styl
create : myapp/routes
create : myapp/routes/index.js
create : myapp/views
create : myapp/views/index.jade
create : myapp/views/layout.jade

install dependencies:
  $ cd myapp && npm install
  
run the app:
  $ DEBUG=myapp node app
  

Like any other node application, you must then install the dependencies:

$ cd myapp
$ npm install

Then fire it up!

$ npm start

That's all you need to get a simple application up and running. Keep in mind that Express is not bound to any specific directory structure, these are simply a baseline for you to work from. For application structure alternatives be sure to view the examples found in the github repo.

Error handling

Error-handling middleware is defined just like regular middleware, except that must be defined with an arity of 4 (that is the signature (err, req, res, next)):

app.use(function(err, req, res, next){
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

Though not mandatory, error-handling middleware are typically defined very last, below any other app.use() calls, like so:

var bodyParser = require('body-parser');
var methodOverride = require('method-override');

app.use(bodyParser());
app.use(methodOverride());
app.use(app.router);
app.use(function(err, req, res, next){
  // logic
});

Responses from within the middleware are completely arbitrary. You may wish to respond with an HTML error page, a simple message, a JSON string, or anything else you prefer.

For organizational (and higher-level framework) purposes, you may define several error-handling middleware, much like you would with regular middleware. For example suppose you wanted to define an error-handler for requests made via XHR, and those without, you might do:

var bodyParser = require('body-parser');
var methodOverride = require('method-override');

app.use(bodyParser());
app.use(methodOverride());
app.use(app.router);
app.use(logErrors);
app.use(clientErrorHandler);
app.use(errorHandler);

Where the more generic logErrors may write request and error information to stderr, loggly, or similar services:

function logErrors(err, req, res, next) {
  console.error(err.stack);
  next(err);
}

Where clientErrorHandler is defined as the following (note that the error is explicitly passed along to the next):

function clientErrorHandler(err, req, res, next) {
  if (req.xhr) {
    res.status(500).send({ error: 'Something blew up!' });
  } else {
    next(err);
  }
}

The following errorHandler "catch-all" implementation may be defined as:

function errorHandler(err, req, res, next) {
  res.status(500);
  res.render('error', { error: err });
}

Users online count

This section details a full (small) application that tracks a users online count using Redis. First up, you'll need to create a package.json file containing two dependencies: one for the redis client, and another for Express itself. (Also, be sure you have redis installed and running via $ redis-server.)

{
  "name": "app",
  "version": "0.0.1",
  "dependencies": {
    "express": "3.x",
    "redis": "*"
  }
}

Next you'll need to create an app, and a connection to redis:

var express = require('express');
var redis = require('redis');
var db = redis.createClient();
var app = express();

Next up is the middleware for tracking online users. Here we'll use sorted sets, so that we can query redis for the users online within the last N milliseconds. We do this by passing a timestamp as the member's "score". Note that we're using the User-Agent string here, in place of what would normally be a user id.

app.use(function(req, res, next){
  var ua = req.headers['user-agent'];
  db.zadd('online', Date.now(), ua, next);
});

This next middleware is for fetching the users online in the last minute using zrevrangebyscore to fetch with a positive infinite max value, so that we're always getting the most recent users. It's capped with a minimum score of the current timestamp minus 60,000 milliseconds.

app.use(function(req, res, next){
  var min = 60 * 1000;
  var ago = Date.now() - min;
  db.zrevrangebyscore('online', '+inf', ago, function(err, users){
    if (err) return next(err);
    req.online = users;
    next();
  });
});

Finally we then use it, and bind to a port! That's all there is to it. Visit the app in a few browsers and you'll see the count increase.

app.get('/', function(req, res){
  res.send(req.online.length + ' users online');
});

app.listen(3000);

Express behind proxies

Using Express behind a reverse proxy (such as Varnish or Nginx) is trivial; however, it does require configuration. By enabling the "trust proxy" setting via app.enable('trust proxy'), Express will have knowledge that it's sitting behind a proxy and that the X-Forwarded-* header fields may be trusted. (Otherwise, they are easily spoofed.)

Enabling this setting has several subtle effects. The first is that X-Forwarded-Proto may be set by the reverse proxy to tell the app whether it is https or simply http. This value is reflected by req.protocol.

The second change is that the req.ip and req.ips values will be populated with X-Forwarded-For's list of addresses.

Debugging Express

Express uses the debug module internally to log information about route matches and application mode. To see this information, simply set the DEBUG environment variable to express:* when launching your app and the debug information will appear on the console.

$ DEBUG=express:* node ./bin/www

Running this on the hello world example would print the following

express:application booting in development mode +0ms
express:router defined get /hello.txt +0ms
express:router defined get /hello.txt +1ms

Additionally, the app generated by the express executable (generator) also uses the debug module and by default is scoped to the my-application debug namespace.

You can enable those debug statements with the following command

$ DEBUG=my-application node ./bin/www

For more documentation on debug, see the debug guide