極私的なexpressの使い方

expressは使いやすいのですがappにroutingを足していくと長くなってきて読みにくくなったり、基本的な渡すlocalsが一緒だったりとするので、こんなふうに使っています

  • ディレクトリ構成に下記を追加
    • locals
      • jp.js, en.js (これはアプリに合わせて)
    • controllers
      • index.js, entry.js(これはアプリに合わせて)
    • config.js
  • app.js
var express = require('express'),
    app = module.exports = express.createServer(),
    config = app.config = require('./config.js'),
    locals = app.locals = require('./locals').jp,
    logfh = require('fs').createWriteStream('./logs/access.log', {flags: 'w', encoding: 'utf8', mode: '0644'}),
    log4js = require('log4js'),
    sysLogger = app.sysLogger;
log4js.addAppender(log4js.fileAppender('./logs/system.log'), 'sysLogger');
sysLogger = log4js.getLogger('sysLogger');

// Configuration
app.configure(function(){
  app.set('port', 8080); // 基本的には8080ポートで
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.logger({format: ':method :date :status :url :response-time :remote-addr :referrer', stream: logfh}));
  app.use(express.cookieParser());
  app.use(express.session({secret: 'CareerUp', store: new RedisStore}));
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
  app.set('port', 80);
  app.use(express.errorHandler());
});

// Routes
require('./controllers');

// Only listen on $ node app.js
if (!module.parent) {
  app.listen(app.settings.port);
  console.log("Express server listening on port %d", app.address().port);
}
  • controller/index.js
var app = module.exports = module.parent.exports,
    fs = require('fs'),
    path = require('path'),
    files = fs.readdirSync(__dirname),
    locals = app.locals,
    utils = require('connect').utils,
    merge = utils.merge;

for(var i in files){
  if(files[i] !== path.basename(__filename) && // 自身(index.js)を無視
     files[i].indexOf('.') !== 0 && // 隠しファイルやviのswapファイル無視
     files[i].indexOf('~') !== (files[i].length - 1)){ // emacsの一時ファイル無視
    require(__dirname + '/' + files[i]);
  }
}

// "/"だけはこのファイルで設定する
app.get('/', function(req, res){
  res.render('index', merge( // 個別の要素を足し合わせる
    {
      entries: [{title: 1},{title:2},{title:3}]
    },
    locals));
});
  • locals/index.js
module.exports = exports = {
  jp: require('./jp.js'),
  en: require'./en.js')
}
  • locals/jp.js
module.exports = exports = {
  title: 'title',
  error: undefined,
  login: 'ログイン',
  logout: 'ログアウト',
  edit: '編集',
  navi: {
    next: '次へ',
    prev: '前へ'
  }
};