Yeomanでフロントエンドとバックエンドサーバを一緒に開発する
先月、HTML5など勉強会に参加した時、雑談タイムで
「 yeoman を使ってバックエンドの開発とかできないですか? 」
という内容に対して、フォローとして
「 gruntでリバースプロキシ使えますよ 」
っていうお話をした。
そのまま記事に書かずじまいで申し訳ないなーと思っていたら、@bathtimefish さんがブログをアップされていた。
その記事、
YeomanでフロントエンドとREST APIサーバーを同時に開発する方法
でリバースプロキシを使った手法が挙がっていたのですが、gruntのモジュールを使うともう少し楽ができそう。
私は、easymock を知らなかったですし、やはりyeoman 使ってる人が周りにあまりおらず、前回の勉強会は非常に勉強になったので、ここは一つ御礼の意味を込めてブログを書こうと思います。
ということで、yeoman(grunt) を使ったバックエンド開発のもう一つの手法を書いておきます。
さてここからが本題。
ベースとなる手順は元の記事を見ていただきつつ、途中まではだいたい同じです。
Yeomanは使える環境が整っているのが前提。
使えない場合はYeoman 導入編を参照してみてください。
まず REST APIサーバのモックが簡単に作れる easymock をインストール
$ npm install -g easymock
Node.jsのv0.10.1 ではインストールできなかったので今回はv0.8.14で。
次にyeomanでフロントエンドの環境を構成
$ mkdir /path/to/test
$ cd /path/to/test
$ yo webapp
_-----_
| |
|--(o)--| .--------------------------.
`---------´ | Welcome to Yeoman, |
( _´U`_ ) | ladies and gentlemen! |
/___A___ '__________________________'
| ~ |
__'.___.'__
´ ` |° ´ Y `
Out of the box I include HTML5 Boilerplate, jQuery and Modernizr.
Would you like to include Twitter Bootstrap for Sass? (Y/n) y
Would you like to include RequireJS (for AMD support)? (Y/n) y
...(省略)
それから、easymock 用のフォルダを作成。
$ mkdir -p server/api-server/api/items
次に easymock の設定ファイルを作成
$ vim server/api-server/api/config.json
{
"simulated-lag": 1000,
"cors": false,
"jsonp": false,
"proxy": {
"server": "http://api.realserver.com",
"default": false
},
"variables": {
"server": "http://api.realserver.com"
},
"routes": [
"/items/:itemid"
]
}
モックとなるjsonを作成
$ vim server/api-server/api/items/_get.json
[
{ "id": 1, "user": "john", "message": "hello" },
{ "id": 2, "user": "bob", "message": "Hi!" },
{ "id": 3, "user": "mike", "message": "good bye." }
]
APIモック用のサーバーをたちあげてみます。
$ cd server/api-server
$ easymock
Server running on http://localhost:3000
Server running on http://localhost:3000/_documentation/
http://localhost:3000/api/items/
にアクセスすると配置したjsonファイルが出力されています。
[
{
"id": 1,
"user": "john",
"message": "hello"
},
{
"id": 2,
"user": "bob",
"message": "Hi!"
},
{
"id": 3,
"user": "mike",
"message": "good bye."
}
]
では、フロント側を構成していきます。
$ cd /path/to/test/
まず、index.htmlのコンテナ部分を書き換えます。
$ vim /app/index.html
<div class="container">
<div class="hero-unit">
<h1>API Data</h1>
<ul>
</ul>
<h3>Enjoy coding! - Yeoman</h3>
</div>
</div>
次にapp.coffeeファイルを作成します。
$ vim /app/scripts/app.coffee
define(['jquery'], ($)->
'use strict'
$.getJSON('api/items/', (data)->
ul = document.querySelector('div.hero-unit > ul')
for row in data
li = document.createElement 'li'
txt = document.createTextNode "#{row.id}, #{row.user}, #{row.message}"
li.appendChild txt
ul.appendChild li
)
'loading api data.'
)
ひとまずyeoman単独で動かしてみます。
$ grunt server
$.getJSONの取得先がないのでscriptで取得しようとしてるjsonの値は表示されていません。
で、ここからが元記事と違うところですね。
grunt にリバースプロキシ用のモジュールがあるのでそれを使います。
- grunt-connect-proxy
- https://github.com/drewzboto/grunt-connect-proxy
内部的にhttp-proxyを呼んでいるのですが、Gruntfile.js で管理できるので非常に便利です。
$ npm install -D grunt-connect-proxy
-D (--save-dev) は インストールしたモジュールをpackage.jsonに書き込むためにオプションで指定します。
次にリバースプロキシの設定を行います。
- 1, プロキシ用スニペットのロード
- 2, プロキシの設定(/api 対象)
- 3, configureProxies タスクの追加
$ vim Gruntfile.js
'use strict';
var lrSnippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet;
//(proxy用スニペットを追加)・・・1
var proxySnippet = require('grunt-connect-proxy/lib/utils').proxyRequest;
var mountFolder = function (connect, dir) {
return connect.static(require('path').resolve(dir));
};
//...(省略)
connect: {
options: {
port: 9000,
// change this to '0.0.0.0' to access the server from outside
hostname: 'localhost'
},
livereload: {
options: {
middleware: function (connect) {
return [
lrSnippet,
proxySnippet, //スニペット追加・・・1
mountFolder(connect, '.tmp'),
mountFolder(connect, 'app')
];
}
}
},
//プロキシ設定・・・2
proxies: [{
context: '/api',
host: 'localhost',
port: '3000',
https: false,
changeOrigin: false
}],
test: {
//...(省略)
}
});
grunt.registerTask('server', function (target) {
if (target === 'dist') {
return grunt.task.run(['build', 'open', 'connect:dist:keepalive']);
}
grunt.task.run([
'clean:server',
'concurrent:server',
'configureProxies', //タスク追加・・・3
'livereload-start',
'connect:livereload',
'open',
'watch'
]);
});
};
yeomanのフロントサーバをたちあげてみます。
(裏でeasymockを起動するのを忘れずに)
$ grunt server
...(省略)
Running "configureProxies" task
Proxy created for: /api
Running "livereload-start" task
... Starting Livereload server on 35729 ...
Running "connect:livereload" (connect) task
Starting connect web server on localhost:9000.
...(省略)
yeoman側のフロントサーバが起動していますが、/api 以下のアクセスに対しては 3000ポート(easymock側)のAPIサーバを叩いています。
http://localhost:9000/api/items
へアクセスすると、
http://localhost:3000/api/items
の内容が表示されていることがわかります。
ちなみにGruntfile.jsのプロキシ設定のcontextの値を「/」にすると9000番ポートへのすべてのアクセスが3000番ポートへと流れます。
proxies: [{
context: '/',
host: 'localhost',
port: '3000',
https: false,
changeOrigin: false
}],
この場合、フロントで起動するyeoman(grunt server)の役目はLiveReloadだけになり、バックエンドのサーバの内容が表示されます。
あとはwatchするファイルを適宜修正すればOKです。
もう少しYeomanでの管理構成として踏み込むとするなら easymock を別で起動するのが面倒なので、grunt から node の child_process を使って一括で起動管理したいところです。
ここで書くと設定が見辛くなるのでまた次の機会に。
□□□□□□
リバースプロキシを使うことによって、バックエンドがApacheやnginx、Node.jsでもなんでも使えます。
ですので、今回はeasymockをバックエンドサーバとして起動していましたが、WordPressなんかも動かしつつテーマのCSSを監視してライブリロードかけたりできますし、私はNode.jsを使うので、Expressの構成でcoffeeとSassのライブリロードしたりするテンプレートをつくったりして非常に楽しく開発ができてはかどります。
ということで一度使ってみてはいかがでしょう。