How do I add to 'view options' in Express?

I am learning to use Express. I want to do:

app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.set('view options', { layout: false });    /* asterisk */
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);                           /* dagger */
  app.use(express.static(__dirname + '/public'));
});

app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
  app.use(express.logger('dev'));
  app.set('view options', { pretty: true });     /* asterisk */
});

The additions I made were:

  • use 'layout:false' for Jade.
  • pretty-print the HTML in Jade.
  • turn on the logger, with the 'dev' format

There are two problems:

  1. /* asterisk */ when I set 'pretty: true' I am overriding my previous options, rather than adding to them. I.e., my program breaks unless I add { pretty: true, layout: false } which feels redundant and can't be correct. How can I correct it so that I am only "modifying" the view options, rather than "defining" them?

  2. /* dagger */ The logger does not acknowledge my requests, except for /favicon.ico. I find if I remove the app.use(app.router); line, then I'll see both / and /favicon.ico. What is going on here?

I checked in the express source code and the app.set function simply assigns over top of any previous value it had. To get the behavior you're looking for you'll have to merge the view options object in subsequent calls. This means you'll probably have to jump through a couple of hoops. The connect package has a merge function that will work for this but to get it you'll have to include it in your package.json:

"dependencies": {
  "express": "2.5.5"
, "jade": ">= 0.0.1"
, "connect": "1.X"
}

You'll need to get the utils object from connect:

var utils = require('connect').utils;

app.set(option) with no value returns the current setting for the option so the second time you set view option you could do it this way:

app.set('view options', utils.merge(app.set('view options'), { pretty: true }));

As for the problem you're having with the logger, remember that app.use is adding pieces of middleware to a stack. As a request is being processed it calls each piece of middleware in the order they are originally configured and sometimes if a piece of middleware is able to fulfill its duty it will not pass control to subsequent middleware in the stack.

This is the case with the router middleware when it fulfills a request for the '/' url where logger is not subsequently run. The reason the request for favicon.ico shows up in the log stream is that none of the middleware was able to fulfill it (the static middleware would if you had a public/favicon.ico file) and processing falls through to the logger middleware.

To make your example work you'll need to define the logger middleware earlier in your stack, before the router middleware.

As of Express 3.x the use of app.set('view options') is no longer the correct way. https://github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x These options are now set in your app.js using app.locals as in

app.locals.pretty = true;

or to set custom delimiters for ejs

app.locals.open = '}}';
app.locals.close = '{{';