Express 用のテンプレートエンジンを自作する方法

Node.js 用 Web フレームワーク Express のテンプレートエンジンを自作する方法をご紹介します。

といっても自作テンプレートエンジン側で以下のような処理を用意するだけなので、非常に簡単です。

exports.__express = function(path, options. fn) {
    /*
     * 処理に成功すれば        fn(null, テンプレート処理結果)
     * 何かエラーが発生すれば  fn(err)
     * をそれぞれ実行すればよい
     */
     ・・・
};

path にはテンプレートファイルのパス、options にはテンプレート処理用のパラメータが渡ってきます。fn は Node.js ではおなじみのエラーと処理結果を引数にとるコールバックです。


それでは、CoffeeScript を使って Express 用の自作テンプレートエンジン "sample" を作成してみます。

サンプルソースは http://github.com/fits/try_samples/tree/master/blog/20120616/

Express プロジェクトの準備

まず、Express の実行環境を用意します。
今回は、以下のようなパッケージファイルをカレントディレクトリに用意して npm install を実行しました。

package.json
{
  "name": "express_template_sample",
  "version": "1.0.0",
  "dependencies": {
    "express": "3.0",
    "coffee-script": "*",
    "underscore": "*"
  }
}
npm install 実行
> npm install

npm http GET https://registry.npmjs.org/underscore
npm http GET https://registry.npmjs.org/express
npm http GET https://registry.npmjs.org/coffee-script
・・・

なお、環境変数 PATH に node_modules/.bin を追加しておけば、カレントディレクトリで coffee コマンドを使用できます。

ちなみに、Express を使うだけなら CoffeeScript や Underscore.js は不要です。

自作テンプレートエンジン sample の作成

node_modules ディレクトリに自作テンプレートエンジン名のディレクトリ (今回は sample) を作成し、index.coffee (Node.js なら index.js) に exports.__express の処理を実装します。*1

node_modules/sample/index.coffee
fs = require 'fs'
_ = require 'underscore'

exports.__express = (path, options, fn) ->
    try
        res = _.template fs.readFileSync(path).toString(), options
        fn null, res
    catch err
        fn err

テンプレートファイル(path)をテンプレート処理し処理結果をコールバックに渡します。

今回は Underscore.js の template 関数を使ってテンプレート処理を行いました。

テンプレートとメインプログラム作成

まず、テンプレートエンジン名を拡張子に使ったテンプレートファイルを views ディレクトリに用意します。
Underscore.js の template 関数では値を埋め込む箇所に <%= ・・・ %> が使えます。(EJS と同様)

views/index.sample
<html>
<body>
<p><%= title %></p>
</body>
</html>

次に、Express のメインプログラムを作成します。

app.coffee
express = require 'express'

app = express()

app.configure ->
    # デフォルトの view engine を sample に設定
    app.set 'view engine', 'sample'

app.get '/', (req, res) ->
    # index.sample をテンプレート処理
    res.render 'index', {title: 'test'}

app.listen 3000, -> console.log "server started"

/ へのアクセスで index.sample をテンプレート処理するように実装しています。

なお、app.set 'view engine', ・・・ でデフォルトの view engine を設定しておくと、res.render の際に拡張子の指定を省略する事ができます。

動作確認

coffee コマンドで app.coffee を実行した後、http://localhost:3000/ にアクセスすると "<%= title %>" の箇所が "test" に置換されたコンテンツが返ってきます。

実行
> coffee app
server started
処理結果
$ curl http://localhost:3000/

<html>
<body>
<p>test</p>
</body>
</html>

*1:Linux などであれば node_moudules に sample のシンボリックリンクを作成しても可です