概要
こんにちは nyamadori です。
Node.js には Rails のようなこれといった定番の Web フレームワークがありません。
「とりあえず Express でいいや」みたいな風潮がある気がします。
そう思っている方、Sails.js を使ってみましょう!
Sails.js は API ファーストな Web アプリケーションがさくっと実装できるコンパクトな Web フレームワークです。
この記事では、簡単なチャットアプリを作りながら Sails.js を紹介します。
(一体何番煎じの内容だろうか…)
チャットアプリを作る
これから、以下のような簡単なチャットアプリを作っていきます。
- 2つのクライアント間でチャットができる
- アカウント管理はしない。どちらが投稿したメッセージかを区別できる必要はない
- 一方がメッセージを投稿すると、もう片方の側でもメッセージが同期される
以降の説明は、2014/12/17 現在で最新の Sails 0.10.5 が前提です。
インストール
$ sudo npm install -g sails
アプリケーションの作成
まず sails new
でアプリケーションのひな形を作ります。
$ sails new chat
サーバの起動
ひな形を作ったら、サーバを起動してみましょう。
$ cd chat
$ sails lift
Web ブラウザで http://localhost:1337/
を開いて以下のページが表示されたら、正常に起動できています。
チャットのメッセージを扱う RESTful な API を作る
まずはチャットのメッセージを扱うモデルと、そのモデルに対するリクエストを処理するコントローラを作りましょう。
sails generate
コマンドで、コントローラやモデルを作ることができます。
$ sails generate controller message
$ sails generate model message
Sails では、データベースのクエリやルーティングを書かなくても、
モデルと同名のコントローラがあれば、デフォルトで RESTful なリクエストを処理してくれます。
サーバを再起動して、curl
コマンドでリクエストするとレスポンスがちゃんと JSON で返ってきます。
コントローラの名前もモデルの名前もデフォルトで単数形です。
$ sails lift
$ curl localhost:1337/message # GET /message => MessageController#find
[]
$ curl -F 'body=hoge' localhost:1337/message # POST /message => MessageController.create
{
"body": "hoge",
"createdAt": "2014-12-16T19:14:58.597Z",
"updatedAt": "2014-12-16T19:14:58.597Z",
"id": 1
}
モデルのバリデーション
さすがにメッセージが空の投稿を許可するわけにはいかないので、バリデーションを設けます。
$ editor api/models/Message.js
/**
* Message.js
*
* @description :: TODO: You might write a short summary of how this model works and what it represents here.
* @docs :: http://sailsjs.org/#!documentation/models
*/
module.exports = {
// attributes に各属性の型、バリデーション、関連を記述する
attributes: {
body: {
type: 'string', // データ型
required: true // 必須であることを表す
}
}
};
サーバを再起動して、curl
コマンドで body
を空にしてリクエストすると、エラーレスポンスが JSON で返ってきます。
クライアント側でレスポンスのエラー判定を行うときは、if (res.error) ...
とすれば良いことになります。
$ sails lift
$ curl -F 'body=' localhost:1337/message # POST /message => MessageController.create
{
"error": {
"error": "E_VALIDATION",
"status": 400,
"summary": "1 attribute is invalid",
"model": "Message",
"invalidAttributes": {
"body": [ /*(略)*/ ]
]
}
}
}
クライアントサイドの実装
サーバサイドの実装は以上で終わりです。
ここからは、クライアントサイドのビューやJavaScriptの実装方法について説明します。
Vue.js の導入
クライアントサイドの MVVM フレームワークとしてこのアプリケーションでは Vue.js を使います。
一番説明が簡単だったので、Vue.js にしました。
事前に Vue.js をダウンロードして、vue.js
または vue.min.js
を assets/js/dependencies/
にコピーしてください。
assets/js/dependencies/
は、アプリケーション外部の JavaScript ファイルを入れるディレクトリです。
assets/js/
以下に入っている JavaScript ファイルは自動で HTML ファイルに挿入され、読み込まれます。
ビューの記述
今までに投稿されたメッセージの表示、投稿ができる画面 (ビュー) を作成します。
views/homepage.ejs
には Sails デフォルトのホーム画面の HTML (ejs) が入っていますが、不要なのですべて消して以下の内容に書き換えます。
<ul>
<li v-repeat='messages'>{{body}}</li>
</ul>
<form v-on='submit: create'>
<input v-model='newMessage.body' type='text' placeholder='メッセージ (Enter で投稿)'>
</form>
ViewModel の作成
メッセージの表示や投稿を処理するために Vue.js の ViewModel を作ります。
Sails には標準でサーバの API にアクセスするための JavaScript ライブラリが用意されており、モデルのデータに変更があった場合は、SocketIO 経由でモデルの変更をクライアントに通知してくれます (設定で変更可能)。
var app = new Vue({
el: 'body',
data: {
messages: []
},
events: {
'message:created': function (message) {
this.messages.push(message);
}
},
created: function () {
var _this = this;
// サーバに GET /message としてリクエストする
io.socket.get('/message', function (res) {
_this.messages = res;
});
// io.socket.on でモデルの変更イベントを監視できる
io.socket.on('message', function (event) {
// event.verb が変更の種類を表す
switch (event.verb) {
case 'created': // created: モデルに新たなデータが追加された
_this.$emit('message:created', event.data);
break;
}
});
},
methods: {
create: function (event) {
event.preventDefault(); // submit 時のページ遷移を無効にする
var _this = this;
// サーバに POST /message としてリクエストする
io.socket.post('/message', this.newMessage, function (res) {
if (res.error) {
return console.error(res.error);
}
_this.$emit('message:created', res);
});
}
}
});
完成
サーバーを再起動し、ブラウザを2つ立ち上げてメッセージを投稿すると、ちゃんと両方のブラウザでメッセージが同期されます。
まとめ
-
モデルと同名のコントローラがあれば、自動的に RESTful なリクエストを処理してくれる
- モデルのデータを加工せずにそのまま返す単純な API なら何も書かなくて良い!
-
モデルのデータに変更があったら、モデルの変更をクライアントに通知してくれる
注意
あくまで Sails.js の紹介なので、本番環境は考慮していません。
本番環境に合わせて適宜設定を変更してください。