これは Heroku Advent Calendar 2014 の21日目(12/21)の投稿です。
最近はクライアント(ネィティブアプリ、JavaScriptベースのWEBアプリ)とサーバを RESTful な WEB API でつなぐパターンが増えてきてる気がしています。エンドユーザ向けのサービスだけでなく、管理画面やツールなどでも。
今回は AngularJS Full-Stack(generator-angular-fullstack) を利用して Node.js(Express) と MongoDB ベースの RESTful な API サーバ を作り Heroku へデプロイするまでやってみます。(AngularJS の環境は、今回は使いません。フロントエンドは AngularJS をそのまま使ってもいいし、それ以外にしてもOK。)
『AngularJS Full-Stack』には Heroku 用のコマンドが用意されています。ただ、自分で Heroku デプロイしてもたいして大変ではないのですが。
AngularJS Fullstack について
これは所謂 MEAN スタック(MongoDB/Express/AngularJS/Node.js)なのですが、クリティカルでないアプリケーションをさっと作ったり、ツール類の作成、またはモック作成用にいいな、と思っています。
同じようなジェネレータに MEAN.JS があるのですが、AngularJS Full-Stack の方が縛りが弱く、後から手を加えやすい印象だった。また他の Express 系のジェネレータは、サーバ側で HTML を生成してレスポンスすることを想定しており、API を作るのにはそれほど適してなさそうな感じがした。
Epress ベースのもの以外では Sales.js を使えば似たようなことが出来るのかもしれませんが、これは良く分かっていない.. そのほか Node.js のフレームワークについては、ここで色々あげられています。
⇒ http://nodeframework.com
AngularJS Full-Stack の使い方については、GitHub のページに書いてあります。
⇒ https://github.com/DaftMonk/generator-angular-fullstack
$ yo angular-fullstack:endpoint hoge
で、hoge
モデルおよび RESTful な API 一式を生成することができます。
今回の前提環境
私の手元の環境は次のとおりです。
OS:
Mac OS X 10.9.5
YEOMAN(yo):1.3.2
AngularJS Full-Stack(generator-angular-fullstack):2.0.13
Node.js:0.10.32
MongoDB:2.6.5
Heroku Toolbelt:3.20.0
※ それぞれを Mac に導入する手順については、ここでは割愛します。
また、今回の手順で結果的に導入された主要なモジュールのバージョンは次のとおりです。
Express:
4.0.0
Mongoose:3.8.20
Grunt:0.4.5
IDE は WebStorm を使ってます。MongoDB のプラグインもあり便利。
手順
ローカル環境構築
プロジェクト用のディレクトリを適当につくり、配下でジェネレータを起動します。
$ mkdir api_demo
$ cd api_demo
$ yo angular-fullstack
ジェネレータが無い場合は
$ npm install -g generator-angular-fullstack
で導入してください。
適当に質問に答えます。
Client側(AngularJS側)は利用しないので(してもいいんだけど)、何でもいいです。
Server側(Node.js側)は、MongoDB の項だけ有効にします。
ジェネレータがプロジェクトを生成してくれるまでしばらく待ちます。生成が終わったら、
$ grunt serve
で確認します。(MongoDB はローカルのデフォルトポートで起動しておいてください。)
上記の画面は、ジェネレータ起動時に選択したオプションにより異なると思います。次に、肝心の API について動作確認してみます。デフォルトで thing
モデルと RESTful な API 一式が生成されており、
先ほどの $ grunt serve
時に、MongoDB へ Seed データも挿入されています。
一覧データを取得してみます。$ grunt serve
のプロセスを起動したままの状態で http://localhost:9000/api/things/
にアクセスしてみます。次のようにデータが取得されるはずです。
新しくモデルと RESTful API を作る
例として、item
モデルの RESTful な API 一式を作成します。先ほどの thing
モデルを参考にソースを書いても良いのですが、せっかくジェネレータがあるので利用してみます。
$ yo angular-fullstack:endpoint item
? What will the url of your endpoint to be? (/api/items)
そのまま進めます。(URLを変えたければ指定してください。)
モデルのファイルを修正します。適当に name
price
description
というカラムを定義しました。
'use strict';
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var ItemSchema = new Schema({
name: String,
price: Number,
description: String
});
module.exports = mongoose.model('Item', ItemSchema);
一応 $ grunt serve
し直してから、http://localhost:9000/api/items/
にPOSTしてみます。
MongoDB の中身を覗くと、データが作成されています。
GET http://localhost:9000/api/items/:id
で先ほどPOSTしたデータを取得してみます。
ちょっと表示が文字化けしてますが^^; きちんと動いているようですね。提供される API 郡は次のように、Rails とかで作られるようなものと同じです。
〜
router.get('/', controller.index);
router.get('/:id', controller.show);
router.post('/', controller.create);
router.put('/:id', controller.update);
router.patch('/:id', controller.update);
router.delete('/:id', controller.destroy);
〜
ジェネレータで生成されるもので賄えない場合は、ソースの中身は単純なので、ここからカスタマイズをすれば良いかと思います。
Heroku へのデプロイ
MongoDB のアドオンが必要です。下記の MongoLab
は Sandbox プランだと無料なので、これを使ってみます。(無料のアドオンでも、アドオンを追加するためにはアカウントにクレジットカードを登録しておく必要があります。)
デプロイは簡単で、下記のコマンドを叩くと、
$ yo angular-fullstack:heroku
? Name to deploy as (Leave blank for a random name):
? On which region do you want to deploy ? (Use arrow keys)
❯ US
EU
URLをここで決めれますが、他のユーザ含めた全 Heroku アプリケーションで一意である必要があります。指定しなければランダムで振られます。
dist
ディレクトリにデプロイ用のファイルが展開されて、
その中で勝手に Git 管理がはじまり $ heroku create
諸々のことが自動でされます。
(このプロジェクトを Git で管理している場合は、すでに dist
フォルダはデフォルトで .gitignore
に追記されているのですが、dist
ディレクトリ配下は Heroku に関する Git 管理下になる感じです。)
ただこのままだと MongoDB のアドオンが無いのでエラーになります。次のように追加します。
$ cd dist
$ heroku addons:add mongolab
追加したら、Heroku 側を開いてみます。
$ cd dist
$ heroku open
もちろん API も利用できます。
何かおかしければ $ heroku ps
や $ heroku logs
、$ heroku config
で Heroku 上のステータスを確認してみましょう。(Heroku のダッシュボートを見てもいいけど。)
補足:Heroku 系のコマンドについて
yo angular-fullstack:heroku
コマンドを使わなくても、$ grunt build
したら dist
ディレクトリにデプロイ用のファイルが展開されるので、dist
ディレクトリ配下で $ heroku create
してデプロイしても良いかと。
Heroku 上の環境変数
NODE_ENV
をproduction
にしておく必要があります。
まあせっかくコマンドが用意されているので、それを使えばよいのですが..
補足:自前サーバにデプロイする場合
Node.js と MongoDB が用意されたサーバに dist
ディレクトリ配下のファイルを置いて、$ npm install --production
、$ npm start
すればよいかと思います。
こちらも自前サーバ上で環境変数
NODE_ENV
をproduction
にしておく必要があります。
Heroku へデプロイしたアプリケーションの更新
$ grunt build
してから $ grunt buildcontrol:heroku
とすると、変更が Heroku へプッシュされます。
おわりに
モック用の API サーバとかさくっと作るには、今回の構成はわりといいなーと思います。今回のソースはこちらに置きました。よろしければ参照ください。
⇒ https://github.com/hkusu/node-apiserver-sample
明日(12/22)のアドベントカレンダーは LuckOfWise さんの記事です。よろしくお願いします!