ここ最近はNode.jsを勉強中で、Socket.IOについては一通りさわれたと思うので、今度はExpressをさわってます。
せっかくなので以前のSocket.IOのチャットアプリをExpressにのせて、以降のNodeの勉強をExpress上でやることにしました。
で、ここからがメモの本題。
Expressを普通にインストールしてSocket.IOを使うサンプルは結構ありますが、それらをそのまま参考にしてるとapp.jsがどんどん肥大化していきます。
なんの根拠もない個人的な理由ですが・・、
- app.jsはサーバーを起動する部分と各種ルーティング機能への橋渡しなど、必要最低限にしたい
- 他にサンプルを作ったときも、うまく結合できる
ので、コードを出来る限り分割することにしました。
正解・最適解かはわかりませんが、一応達成できたのでその記念のメモです。
Expressらしい使い方はまだまだ出来てないので、そこにたどり着くまでの環境整備的な内容ですね。
前提
今回のメモの内容の環境設定です。
- 単一のドメイン以下で実装
- URLに対する一旦のアクセスはNginxで受け、状況に応じてNodeで処理
- Nginxで配布できる静的ファイルはそのまま出力
- Nodeで処理するものは全てExpressで処理
- Socket.IOは他のアプリでも利用できることを想定
- バージョンは、Nodeは0.8.16、Expressは3.0.5、Socket.IOは0.9.13を使用
ちなみに、インストールした時点のapp.jsはserver.jsにリネームしてます。
Nginxの設定
virtual.conf
私の環境では、/etc/nginx/conf.d/virtual.conf です。
# server_nameとか諸々・・・ location / { if ( -f $request_filename ) { break; } if ( -f $request_filename/index.html ) { rewrite (.*) $1/index.html break; } if ( !-f $request_filename ) { proxy_pass http://127.0.0.1:9999; break; } } # その他諸々・・・
ポートは適当。
フォルダ構成
. <- このドメインにおけるnginxのドキュメントルート ├── server.js ├── node_modules │ └── express@3.0.5, socket.io@0.9.13, ejs@0.8.3... ├── apps │ └── socketIoChat.js ├── public │ └── socket-io-chat │ ├── chat.js │ └── style.css ├── routes │ └── main.js └── views ├── index.html └── socketIoChat.html
各フォルダ
説明不要かと思いますが一応。
- server.js: Nodeサーバー起動用にシンプルに
- node_modules: 随時ローカルインストールするので割愛
- apps: アプリごとに逃したいコードはこちら
- public: cssや画像、クライアントサイドのjsなど
- routes: ルーティング用(必要に応じて分割予定)
- views: いわゆるテンプレ
Expressの設定
/* Require / Use */ var express = require('express'), http = require('http'), path = require('path'), routes = require('./routes/main'); /* Express settings */ var app = module.exports = express(); app.configure(function() { app.set('port', process.env.PORT || 9999); app.set('views', __dirname + '/views'); app.set('view engine', 'ejs'); app.use(express.favicon()); app.use(express.logger('dev')); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(path.join(__dirname, 'public'))); // Use .html as view engine. app.engine('html', require('ejs').renderFile); }); /* Env settings */ app.configure('development', function() { app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); }); app.configure('production', function() { app.use(express.errorHandler()); }); /* Url routings */ app.get('/', routes.index); app.get('/socket-io-chat', routes.socketIoChat); /* Create server */ var server = http.createServer(app).listen(app.get('port'), function() { console.log("Express server listening on port " + app.get('port')); }); /* Socket.IO */ var io = require('socket.io').listen(server); app.set('io', io); /* For /socket-io-chat */ require('./apps/socketIoChat');
.ejsではなく.htmlをviewに使う
app.engine('html', require('ejs').renderFile);
requireするモジュール側で、appを参照する
var app = module.exports = express();
Express x Socket.IO
var server = http.createServer(app).listen(app.get('port'), function() { console.log("Express server listening on port " + app.get('port')); }); // ... var io = require('socket.io').listen(server);
検索して見つかったサンプルと違うのはこれくらいかな?
Socket.IOのコードを逃がす
// server.js // ... // app自体を退避 var app = module.exports = express(); // ... var io = require('socket.io').listen(server); // ioをapp.setで一旦退避 app.set('io', io); /* For /socket-io-chat */ require('./apps/socketIoChat');
これである程度見通しの良いままにしておいて・・
// ./apps/socketIoChat.js // app自体を再定義したら参照可能に! var app = module.parent.exports, // 退避したioをappから参照 io = app.get('io'); var socketIoChatSocket = io.of('/chat').on('connection', function(client) { // ... client.emit('connected'); // ... });
これで違うSocket.IOアプリを載せたとしても、server.jsは綺麗なままにできる気がする。
この内部のコードは、以前にサンプルを載せてるので割愛です。(現行ちょっとだけ変わってるけど・・。)
以上、忘れないように。
これからもっとNodeでいろいろやりますよ。
Expressの掘り下げと、fsモジュール関連とかスクレイピングとかもしてみたい。