© 2011 www.GdeFon.com
via. http://www.gdefon.com/animals/552919-cat_for_laptop.html
grunt-express-server
Grunt Plugins Advent Calendar 9日目で、サーバサイド開発との連携で使う grunt-connect-proxy について紹介しましたが、引き続きサーバサイド連携についてです。
-> Grunt Plugins Advent Calendar 9日目:フロントエンドだけじゃない! サーバサイドの開発も手助けしてくれる grunt-connect-proxy を紹介するよ
前置き長めデス。
9日目では、
- フロントサーバとしてgrunt から LiveReload用のサーバを立ち上げ
- プロキシ経由でPHPなどのバックサーバのレイアウトやCSSファイルを監視
- フロントサーバで表示しているブラウザをリロードする
と、解説しました。
ここから Node.jsであれば、Node.js 側の.js ファイルをwatch タスクの対象にしたくなるはずです。
しかし、watchなどのタスクで jsファイルの変更を見るだけでOKということにはなりません。
サーバサイド側の言語がインタプリタ型でかつ、サーバの再起動が必要がなければ、ファイルの変更についてwatchタスクを使ってリロードするだけでOKでした。
しかし、Node.js で.jsファイルを変更した場合、サーバの再起動が必要となります。
そこで一般的に supervisor や、forever 等で.jsファイルの変更を監視、再起動をするという形で開発をすることが多いです。
これに grunt:watich でのjsファイル監視、ブラウザのLiveReload が加わる事になりますが、Nodeサーバの再起動とブラウザのリロードのタイミングが問題になります。
なぜなら、Node.js の再起動した”後"に ブラウザのリロードが実行されなければなりませんが、ファイル変更監視のリロードの方が早い場合がほとんどです。
決め打ちで一定の間隔をおけばいけるのかもしれませんが、それでもやはり失敗する。
そこでエラい人は考えました。Node.jsの再起動時にログ出力をパイプして起動後タイミングの監視すればいいと。
ということで、今回はNode.jsのフレームワーク Express で開発する時に使ってみたいプラグイン grunt-server-express を紹介します。
How to use
npm i -D grunt-express-server
LiveReloadも合わせて行うので grunt-contrib-watch なども利用することになると思います。
必要なパッケージは以下にまとめているので、試してもらったほうが早いかもしれません;;
grunt 実行時に 裏で node サーバをたちあげたいので options
の background
項目は true
に設定します。
通常であれば node
コマンドが使用されるのですが、ファイルの変更でサーバの再起動を行ないたいので (今回は) options
の cmd
項目で forever を使うよう設定しています。
Gruntfile.js
"use strict";
var LIVERELOAD_PORT, folderMount, listen, lrSnippet, mountFolder, proxySnippet, server;
LIVERELOAD_PORT = 35729;
proxySnippet = require("grunt-connect-proxy/lib/utils").proxyRequest;
mountFolder = folderMount = function(connect, base) {
return connect["static"](require("path").resolve(base));
};
listen = 8000;
server = 3000;
module.exports = function(grunt) {
require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);
grunt.initConfig({
connect: {
front: {
options: {
host: "localhost",
port: listen,
middleware: function(connect) {
return [mountFolder(connect, "."), proxySnippet];
},
open: {
target: "http://localhost:" + listen
},
livereload: true
}
},
proxies: [
{
context: "/",
host: "localhost",
port: server + "",
https: false,
changeOrigin: false
}
]
},
express: {
dev: {
options: {
background: true,
port: server,
cmd: "forever",
args: ["-w"],
script: "app.js",
delay: 0
}
}
},
watch: {
options: {
livereload: true
},
express: {
files: ["app.js", "routes/**/*.js", "views/**/*.jade"],
tasks: ["express:dev"]
},
veiw: {
files: ["public/**/*.{js,css}"]
}
}
});
return grunt.registerTask("server", ["configureProxies", "express:dev", "connect:front", "watch"]);
};
packege.json
{
"name": "grunt-express-server-sample",
"version": "0.0.1",
"private": true,
"scripts": {
"preinsall": "npm i -g forever",
"start": "node app.js"
},
"dependencies": {
"express": "3.4.7",
"jade": "*"
},
"devDependencies": {
"grunt-connect-proxy": "~0.1.7",
"grunt-express-server": "~0.4.10",
"grunt": "~0.4.2",
"grunt-contrib-watch": "~0.5.3",
"matchdep": "~0.3.0",
"grunt-contrib-connect": "~0.6.0",
"connect-livereload": "~0.3.2"
}
}
後記
以前、grunt init のパッケージでExpress のLiveReload を実現したいと思って色々試していたのですが、 grunt-regarde (いまならgrunt-contrib-watch) と Node.js のReloadコマンド supervisor とのリロード時間と合わず、なかなかうまくいきませんでした。
そんなことをTwitterに書いた所 @yosuke_furukawa さんに grunt-express-server を教えていたことでこの記事が書けました。ありがとうございます。
後記2
proxy の設定無いほうがわかりやすかったかも ;;