115
109

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Node.jsAdvent Calendar 2014

Day 17

Sails.js と Vue.js で API ファースト + リアルタイムな Web アプリケーションをさくっと作る

Posted at

概要

こんにちは 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/ を開いて以下のページが表示されたら、正常に起動できています。

sails.png

チャットのメッセージを扱う 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
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.jsassets/js/dependencies/ にコピーしてください。

assets/js/dependencies/ は、アプリケーション外部の JavaScript ファイルを入れるディレクトリです。
assets/js/ 以下に入っている JavaScript ファイルは自動で HTML ファイルに挿入され、読み込まれます。

ビューの記述

今までに投稿されたメッセージの表示、投稿ができる画面 (ビュー) を作成します。
views/homepage.ejs には Sails デフォルトのホーム画面の HTML (ejs) が入っていますが、不要なのですべて消して以下の内容に書き換えます。

views/homepage.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 経由でモデルの変更をクライアントに通知してくれます (設定で変更可能)。

assets/js/app.js
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 の紹介なので、本番環境は考慮していません
本番環境に合わせて適宜設定を変更してください。

115
109
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
115
109

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?