Multiple View paths on Node.js + Express

Last Update

The multiple view folders feature is supported by the framework since Express 4.10

Just pass an array of locations to the views property, like so.

app.set('views', [__dirname + '/viewsFolder1', __dirname + '/viewsFolder2']);

Express 2.0

As far as I know express doesn’t support multiple view paths or namespaces at the moment (like the static middleware do)

But you can modify the lookup logic yourself so that it works the way you want, for example:

function enableMultipleViewFolders(express) {
    // proxy function to the default view lookup
    var lookupProxy = express.view.lookup;

    express.view.lookup = function (view, options) {
        if (options.root instanceof Array) {
            // clones the options object
            var opts = {};
            for (var key in options) opts[key] = options[key];

            // loops through the paths and tries to match the view
            var matchedView = null,
                roots = opts.root;
            for (var i=0; i<roots.length; i++) {
                opts.root = roots[i];
                matchedView = lookupProxy.call(this, view, opts);
                if (matchedView.exists) break;
            }
            return matchedView;
        }

        return lookupProxy.call(express.view, view, options)
    };
}

You will enable the new logic by calling the function above and passing express as a parameter, and then you will be able to specify an array of views to the configuration:

var express = require('express');
enableMultipleViewFolders(express);
app.set('views', [__dirname + '/viewsFolder1', __dirname + '/viewsFolder2']);

Or, if you prefer, you can patch the framework directly (updating the view.js file inside it)

This should work in Express 2.x, not sure if it will with the new version (3.x)

UPDATE

Unluckily the above solution won’t work in Express 3.x since express.view would be undefined

Another possible solution will be to proxy the response.render function and set the views folder config until it gets a match:

var renderProxy = express.response.render;
express.render = function(){
    app.set('views', 'path/to/custom/views');
    try {
        return renderProxy.apply(this, arguments);
    }
    catch (e) {}
    app.set('views', 'path/to/default/views');       
    return renderProxy.apply(this, arguments);
};

I’ve not tested it, it feels very hacky to me anyway, unluckily this feature has been pushed back again:
https://github.com/visionmedia/express/pull/1186

UPDATE 2

This feature has been added in Express 4.10, since the following pull request has been merged:
https://github.com/strongloop/express/pull/2320

Leave a Comment