チャットアプリ書き直し

前回一応チャットアプリを作ったけど、あんまりExpressの動きが理解できなかったので、Nodeビギナーズブック公式ガイド公式リファレンスを読んでちゃんと入門してからもういちどチャットアプリを作っていく。

Expressでhtmlファイルを表示する方法

だけど、いきなりhtmlを表示させるところでつまづいた。何の気なしに

res.render('index.html');

みたいなことしようとすると下のようになる。

Error: Cannot find module 'html'

どうも「htmlという拡張子を持つファイル」に割り当てられているテンプレートエンジンが見つからないからエラーになるらしい。

結論

結論から言えば、htmlなどの静的なファイルは

app.use(express.static(__dirname + '/public'));

として、/publicフォルダ以下に置くのがベストということが分かった。

以下その結論に辿り着くまでの顛末。

経緯

そういえばただのhtmlファイルを表示するにはどうするんだろうと思って適当にググってみると、同様の問題がstackoverflowで質問されているのを見つける。回答を見てみると何通りも答えがあって、これといったベストな方法は決まってないらしい。いくつか回答をピックアップする。

app.engine()でhtml拡張子を既存のテンプレートエンジンでレンダリングするようにする

app.engine()(旧名register)は拡張子とテンプレートエンジンを結びつけるメソッド。これを使って.htmlも既存のテンプレートエンジンでレンダリングしてもらうようにするという方法。評価:18

app.engine('html', require('ejs').renderFile);
app.engine('html', require('jade').__express);

app.engine()に自作のhtml用テンプレートエンジンを指定する

上とやることは同じ。けど、ただのhtmlをわざわざテンプレートエンジン使ってレンダリングするのってパフォーマンス的にどうなのってことで、渡された文字列をそのまま返すだけの簡単なhtml用テンプレートエンジンを即興で作ってそれを利用するという方法。突っ込みコメントあり。評価:26

fs.readFile()でファイルを読み込んでres.sendする

そのまんま。だけど、ファイルがキャッシュされないからダメだと指摘されていた。評価:10

express.staticを使う(パフォーマンス的にベスト)

上の方法はどれもなんだかなあって感じの解決法ばっかりで、もういっそのこと拡張子をejsに変えるだけでよしとしようかなあと思っていたら、突っ込みコメントを見てexpress.static()があったことを思い出す。ググって使い方を調べてみると、まさにやりたいことそのものと言えるような内容だった。早速、app.jsに

app.use( express.static(__dirname + '/public') );

を追加。これでpublic/フォルダにindex.htmlを置いておけば、http://localhost/にアクセスしたときにindex.htmlが表示されるようになる。ちなみに、パス関係の便利モジュールを使って次のように書いてもいい。

var path = require('path');
app.use( express.static(path.join(__dirname, 'public')) );

というわけでいとも簡単にできた。ソース → simple_chat_room_2