Node.jsを初めて5日目。
#前置き
いろんなNode関連のサイトを徘徊していると、gruntとか、gulpとかいう言葉が登場します。
しかし私はいずれの言葉もよく知りません。
とりあえず理解できたのは、「いずれもタスクを管理する」ものであること、
また、gulpのほうが新しく、トレンドになりつつあること。
とりあず覚えて損はなさそうなので、試してみます。
いろんな解説サイトがあるけど、まずは、本家のドキュメントを見ながら進めてみます。
#インストール
1.グローバルにインストール
npm install --global gulp
2.現在のプロジェクトにインストール
$ npm install --save-dev gulp
3.gulp.jsを作成する
var gulp = require('gulp');
gulp.task('default', function() {
// place code for your default task here
//デフォルトのタスクを何かかけ
});
4.gulpを実行する
gulp
ちなみに、default
と書いた部分には任意の名前が付けられるようです。
もしtest
という名前にしたならば、gulpを実行する際に、
gulp test
とすればよさそうです。
#gulpで何をするのか
さて、これで一体何をするのでしょうか?
とりあえずこんなことをしてみたいと思います。
####あるフォルダにあるJavaScriptファイルを圧縮する
下記コードでそれができます。
//uglifyは、javascriptファイルを圧縮してくれるプログラムです。
//事前に `npm install gulp-uglify`を実行し、インストールしておく必要があります。
var uglify = require('gulp-uglify');
var gulp = require('gulp');
gulp.task('uglify', function() {
gulp.src('js/*.js')
.pipe(uglify())
.pipe(gulp.dest('js/min'))
});
さて、上記を実行するには、
gulp uglify
とコマンドを入力して実行します。
すると、jsフォルダ内の.js ファイルがすべて圧縮され、js/minフォルダに作成されます。
これは便利ですね。
でも、どうせならファイルが変更されたら勝手に圧縮してほしいものです。
ファイルが変更されたら何かを実行したい場合は、watchが使えます。
上のコードに少しだけ、書き加えます。
gulp.task('uglify', function() {
gulp.watch('js/*.js')
.pipe(uglify())
.pipe(gulp.dest('js/min'))
});
gulp.task('watch',function(){
gulp.watch('js/*.js',['uglify']);
});
gulp.watch()の第二引数に定義したタスク名を指定しています。
コンソールでgulp watch
と入力すると、待ち状態になると思います。
この状態でjsフォルダ内にあるjsファイルを編集すると、
uglify
タスクが呼ばれて、jsフォルダ内のjsファイルをすべて圧縮、コピーしてくれます。
これは便利ですね。
このように、gulpを使うと、あらかじめ決まっている処理をタスクという形で定義しておき、
実行することができるのですね。
#サーバーを自動で再起動してみる。
サーバー再起動が必要なファイルを編集したら、勝手に再起動してほしいですね。
こんな感じでできそうです。
var gulp = require('gulp');
var spawn = require('child_process').spawn;
var server;
gulp.task('server',function(){
if(server){
//サーバーを終了
server.kill('SIGKILL');
}
//サーバーを起動
server = spawn('node',['./bin/www']);
})
gulp.task('watch',['server'],function(){
gulp.watch('js/*.js',['server']);
});
上記をgulp watch
として、コンソールから起動すると
1.'server'タスクの起動と同時に、jsフォルダ以下のjsファイルを監視
2.ファイルに変更があったら、'server'タスクを実行
となります。
##child_process
ここでは、child_processというモジュールを使っています。
簡単に言えば、これで外のプログラムを起動したりできます。
「spawn」は、「産む」とかいう意味です。
例えば
var spawn = require('child_process').spawn;
spawn('ping',['127.0.0.1']);
これを実行すると、コンソール上でpingを打った場合と同じことが起こります。
第一引数がプログラム名、第二引数には、プログラムに渡す引数を配列で指定します。
起動したプログラム(プロセス)終了するときは
kill('SIGKILL');
とすれば終了します。
##他のタスクの実行
ところで、gulp.watchを実行すると、ファイルの変更があった場合には指示した命令を実行してくれますが、watch開始と同時に他のタスクを実行するには
gulp.task('watch',['server'],function(){
というように、第二引数、起動したいタスク名を配列で指定します。
##npm startの中身
server = spawn('node',['./bin/www']);
とありますが、これはnpm start
の中身です。
ここまで、npm start
として、expressを起動していましたが、
これはプロジェクトのルートフォルダにある「package.json」に何をするかが定義してあります。
package.jsonをみると
"scripts": {
"start": "node ./bin/www"
},
と書いてあります。
ですので、これをspawnに渡して
spawn('node',['./bin/www'])
として起動しています。
※spawn('npm',['start'])でも動きそうですが、私はWindowsでnode.jsを使用しています。
windowsの場合、npmはnpm.cmdであり、バッチファイルです。
これはspawnでは起動できません。(spawnで起動できるのはwindowsではexeだけらしい)
どうしてもnpm経由で起動するなら、
spawn('cmd', ['/s', '/c', '"npm"']
とすればイケそうですが、終了時にコマンドは終了するが、プロセスが残る、ということがあるとのこと。この問題についはココ(英語)で語られています。試してはいないです。
##コンソールにエラー出力する
ただしこれだと、expressで出力されるエラーや、console.log(・・・)とした情報は、コンソールに出力されません。
出力するには、下記をgulpfileに追記しておきます。
console.logとかをハンドル
server.stdout.setEncoding('utf8');
server.stdout.on('data',function(data){
console.log(data);
});
//エラーをハンドル
server.stderr.setEncoding('utf8');
server.stderr.on('data',function(data){
console.log(data);
});
##終わり
細かいことを抜きにすれば、これだけで、ファイル監視+サーバー再起動を実施することがき、ctrl+C npm start とコンソールに入力する手間が省けますね。