koaとangularjsとMongoDBでWebAppsを作る

さて、Node.js 日本ユーザグループの新代表になりました。@yosuke_furukawa です。
改めてブログで挨拶します、と言いましたが書きかけのエントリがお正月から眠っているので、一旦溜まったブログを書いてから記述します。

最近やっぱりkoaにはまってて、一個koaでWebアプリを作ってみようかなと思い、Twitterライクな掲示板を作ってみました。

f:id:yosuke_furukawa:20140115090508p:plain

アプリ : http://angular-koa.herokuapp.com/#/

GitHub : yosuke-furukawa/angular-koa · GitHub

koaでRESTFulなapiサーバを作る

一旦koaでRESTFulなapiサーバを作ります、自分で作ってもすごく簡単なのですが、ここでは、api-boilerplate を使いましょう。

api-boilerplateの中身

api-boilerplateはTJがサンプルとして作っているリポジトリで、koaでapiサーバを作る上では格好の教材。面白いので少しだけ紹介します。

api-boilerplateをinstallする

つってもcloneするだけ。まだkoaにはgeneratorがないので、yeomanでgeneratorも作ってみようかと思ってますが、ひとまずcloneしてください。

$ git clone https://github.com/koajs/api-boilerplate.git

api-boilerplateに移動したら、以下の要領で起動することができます。
※ 起動にはredisが必要です、redisがない場合は、インストールして起動しておいてください。

$ node --harmony ./bin/api

デフォルトは4000番ポートで起動するので、起動後にcurl等を使うと動きがわかると思います。

$ curl http://localhost:4000/users

{
  "tobi": {
    "name": "tobi",
    "age": 3,
    "species": "ferret"
  },
  "loki": {
    "name": "loki",
    "age": 2,
    "species": "ferret"
  },
  "jane": {
    "name": "jane",
    "age": 7,
    "species": "ferret"
  }
}

$ curl http://localhost:4000/users/tobi

{
  "name": "tobi",
  "age": 3,
  "species": "ferret"
}

api-boilerplateのライブラリ

api-boilerplateでは下記のライブラリを使っています。

  • koa-response-time, koa-logger (レスポンス記録用)
  • koa-ratelimit (リクエストの処理回数が多くなった時に429, Too Many Requestsを返して一時的にリクエストを受け付けなくするライブラリ、要は人大杉機能、ここでRedisを利用する)
  • koa-compress (レスポンス圧縮用)
  • koa-router (HTTP methodに対してRouterを提供するライブラリ、RESTFulな処理ができる)

koa-routerが少し特殊で、 各種HTTP methodに対して以下のようにメソッドをmappingしています。

app.resource('users', {
  // GET /users
  index: function *(next) {
  },
  // GET /users/new
  new: function *(next) {
  },
  // POST /users
  create: function *(next) {
  },
  // GET /users/:id
  show: function *(next) {
  },
  // GET /users/:id/edit
  edit: function *(next) {
  },
  // PUT /users/:id
  update: function *(next) {
  },
  // DELETE /users/:id
  destroy: function *(next) {
  }
});

api フォルダ以下に下記のような構成を持っています。

api
├── stats
│   ├── config.json -> ルーティングのマッピングを定義することが可能
│   ├── index.js -> いわゆるcontroller
│   └── test.js -> controllerのテストスクリプト

ちなみにこのメソッドを変更する場合は、config.jsonに対してマッピングを定義することも可能です。

MongoDBでデータストアを設定する。

koaでMongoDBを扱う場合、coベースのmongoドライバーを使う必要があります。今回はco-monkを使いました。

実装例:

var monk = require('monk');
var monkWrapper = require('co-monk');
var db = process.env.MONGOLAB_URI ? monk(process.env.MONGOLAB_URI) : monk('localhost:27017/tweets');
var tweets = monkWrapper(db.get('tweets'));

/**
 * GET tweets.
 */

exports.index = function *(){
  var query = this.query;
  var lastId = Infinity;
  if (query.lastId) lastId = +query.lastId;
  var result = yield tweets.find({_id : { $lt : lastId}}, { sort : {_id : -1}, limit : listsNum });
  this.body = result;
};

yieldで結果を取得できる点、monkWrapperでdbを取得している点が特徴的ですね。

Angularjsでクライアントサイドのビューを作る

koaでJSONを返すAPIサーバを作成したので、ビュー側はkoaのテンプレートエンジンではなく、Angularjsでビューを作りましょう。
細かい説明は省きますが、ハマったところとライブラリを紹介します。

angularはyeomanのgeneratorが存在するので、generator-angularで作ればいいかーとか思ってたんですが、generator-angularはNode v0.11をサポートしていません。というか、gruntもサポートしてません。

無理矢理動かそうとすると、エラーになるので、下記のpull requestを参考に修正してください。

Update bower version by yosuke-furukawa · Pull Request #43 · btford/grunt-google-cdn · GitHub

Angularjsの依存ライブラリ

angularjsでは、ngResourceやngRouteなどの標準モジュール以外に以下のライブラリを利用するようにしました。

  • infinite-scroll (いわゆる無限スクロールをサポートするライブラリ)

bower 対応しているので以下の方法で入ります。

$ bower install nginfinitescroll --save

コードはこの辺りを参考にしてください。

https://github.com/yosuke-furukawa/angular-koa/blob/master/app/scripts/controllers/main.js#L15-L28

まとめ

  • koa, mongodb, angularjsでwebアプリを作ってみました。
  • koaでRESTFulなサーバ作るのであればapi-boilerplateが参考になります
  • koaでデータストアを作る場合、coベースのライブラリを利用する必要があります。今回はco-monkを利用しました。
  • ビューはangularjsで作りました。そこまで大したことはしてませんが、無限スクロールをサポートするinfinite-scrollを使ってみました。

感想

Koaで色々作るとライブラリ間が疎なので、色んな物を試せてすごく面白いです。
次はcoとthunkifyでcoベースのライブラリも作ってみようかと思います。