Expressを使ったWebアプリケーション

このエントリは、「東京Node学園 4時限目」の資料その2です。

最初にexpressをインストールをしましょう。

$ npm install -g express

Nodeの場合、必要なパッケージのインストールは npm を用いて行います。-gはグローバルオプションで、これがあるとパッケージは node コマンドがある場所と同じ階層にインストールされます。これがない場合は、現在のディレクトリに node_modules というディレクトリを作成し、その中にインストールされます。
Expressの場合、ひな形を作成する express コマンドが提供されるため、パスの通った場所にそのコマンドを配置する必要があるため、上記のように -g をつけてインストールしています。また、この際、Macでインストーラを使ってインストールした人は sudo を付ける必要があるでしょう。

それでは実際に express コマンドでひな形を作成してみましょう。

$ express sample

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

   dont forget to install dependencies:
   $ cd sample && npm install

で、言われたとおり sample に入って npm install するんですが、その前にディレクトリ構造を確認しましょう。

sample
 ├ app.js 
 ├ package.json
 ├ public
 │  ├ images
 │  ├ javascripts
 │  └ stylesheets
 │       └ style.css
 ├ routes
 │  └ index.js
 └ views
      ├ index.jade
      └ layout.jade

app.js がメインのプログラムで、package.jsonが npm のための設定ファイル。publicが静的ファイル置き場で、routesがルーティングごとのプログラム置き場で、viewsがテンプレート置き場です。
それでは実際に sample に入って npm install しましょう。

$ cd sample && npm install

今回は、Expressのインストール時とは違って、 npm install の後に特定のパッケージ名を指定しませんでした。この場合、 npm は package.json の dependencies に書かれているパッケージをインストールします。インストールされたパッケージは node_modules ディレクトリ内に格納され、プログラムから参照されます。
今回の場合、 Express と jade 及びそれらの依存パッケージがインストールされました。Expressは最初にも(グローバルに)インストールしたじゃないかと思われるかもしれませんが、最初にインストールしたExpressは express コマンドのためだけに利用しており、実際にプログラム中から参照されるのはこの node_modules の中にあるパッケージの方です。

では、メインプログラムである app.js を見てみましょう。


/**
 * Module dependencies.
 */

var express = require('express')
  , routes = require('./routes');

var app = module.exports = express.createServer();

// Configuration

app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  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.use(express.errorHandler());
});

// Routes

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

app.listen(3000);
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);

最初にrequireで必要なパッケージを読み込んでいます。 express がパッケージ名だけで ./routes は相対パス指定になっています。requireは相対パス指定の時はそのファイルもしくはそのディレクトリにある index.js or index.json を読み込み、そうでない場合は コアモジュール もしくは node_modules 内にあるモジュールを読み込みます(実際にはもうちょい細かいです)。

次に express のサーバオブジェクトを作成し、それをモジュールとして公開しています。これによって、例えばテストコードなどからrequireすることでこのサーバオブジェクトを参照することができるようになります。

その後は、設定が続きます。テンプレートの置き場所やテンプレートエンジンの種類、静的ファイルの置き場所等を設定しています。また、developmentモードとproductionモードでの設定の振り分けもしています。ちなみに、デフォルトではdevelopmentモードで起動しますが、環境変数NODE_ENVにproductionを設定すればproductionモードで起動できます。

最後に、ルーティングの設定をして port 3000 を待ち受けています。それでは早速実行してみましょう。

$ node app.js
Express server listening on port 3000 in development mode

ブラウザで http://localhost:3000/ にアクセスして Welcome to Express と表示されたら成功です。
実際にアクセスされた時の動きを順に追っていきましょう。 http://localhost:3000/ にアクセスされると、ルーティングの設定であるように routes.index が実行されます。routes.index は require('./routes').index であり、require('./routes') は ./routes/index.js を読み込むので、./routes/index.js を見てみましょう。

/*
 * GET home page.
 */

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

require('./routes') にはこのexportsが入るため、 routes.index は結局このfunctionになります。
このfunctionでは、レスポンスを描画する際のテンプレートファイルの指定および、変数のバインドをおこなっています。この場合、テンプレートの置き場は./viewsでテンプレートエンジンはjadeだと設定されているので、使用されるテンプレートファイルは ./views/index.jade になります。デフォルトでは同じ場所にあるlayout.jadeが読み込まれ、その body 変数に index.jade の中身がバインドされます。

layout.jade は以下のようになっています。

!!!
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/style.css')
  body!= body

title要素としてtitleにバインドした値を表示し、CSSファイルを読み込んでいます。body要素として表示するのは、次のindex.jadeの中身です(!=はescapeしないで表示するという意味)。

h1= title
p Welcome to #{title}

こちらでも title にバインドした値を2ヶ所に表示しています。jadeの細かい文法は https://github.com/visionmedia/jade をご覧下さい。