鴨のいいカモです

ここでアヒルの話題は出てきません。予めご了承下さい。

Gruntの復習 (4)watchタスクを追加しlivereloadしよう

またかよ禁止。

Gruntの復習 (3)タスクの書き方 - 鴨のいいカモですの続きで、まずはwatchタスクのみとりあげてみることにしました。自分が今Gruntを使っているのはこのwatchタスクがあるからです。watchタスクは、ファイルを監視し、ファイルに変更があると指定したタスクを実行します。これで、変更ごとにコマンドを実行する手間から開放されます。

さらに、livereloadと呼ばれるブラウザ再読み込み機能もあり、とても便利です。ぜひ使いましょう。

ということで、前回作成した以下のGruntfile.jsにwatchタスクを追加してみることにしましょう…の前に、これをCoffeeScriptにしましょう。

module.exports = (grunt) ->
  grunt.initConfig
    # 実行タスク
    uglify:
      options:
        report: 'min'
      dest:
        options:
          beautify: true
        files:
          'dest/js/scripts.min.js': ['src/js/*.js']
      build:
        files:
          'build/js/scripts.min.js': ['src/js/*.js']

  # タスク読み込み設定
  grunt.loadNpmTasks 'grunt-contrib-uglify'

  # タスク定義
  grunt.registerTask 'default', ['uglify']

すっきり!わかりやすい!ということで、さっそくwatchタスクの追加をしましょう。

watchタスクのためのプラグインを探す

プラグイン検索にはPlugins - Grunt: The JavaScript Task Runnerを使うといいでしょう。頭にcontrib-とついてるのはGruntのいわば公式プラグインですので、迷った時はそちらをつかうといいかと。

watchで検索するとgrunt-contrib-watchが出てくるので、それを使いましょう。

grunt-contrib-watchの下準備

まずはいつものようにプラグインを追加します。検索結果から見られるドキュメントgrunt-contrib-watchにあるように、以下のコマンドを実行します。

npm install grunt-contrib-watch --save-dev

そして、Gruntfile.coffeeに以下を追加してタスク読み込みさせます。

grunt.loadNpmTasks 'grunt-contrib-watch'

watchタスクの記述

とても簡単で、基本的にはターゲットに監視対象をfilesで、監視対象変更時に実行したいタスクをtasksで指定するだけです。以下はsrc/js/*.jsの変更時に、タスクuglify:destを実行する例です。

watch:
  scripts:
    files: ['src/js/*.js']
    tasks: ['uglify:dest']

watchタスクの実行

今までと同じように、grunt watchと実行するだけです。すると、以下のように監視状態となります。

% grunt watch
Running "watch" task
Waiting...

ここで、監視対象であるファイルを変更すると…

Waiting...OK
>> File "src/js/a.js" changed.

Running "uglify:dest" (uglify) task
File "dest/js/scripts.min.js" created.
Original: 129 bytes.
Minified: 134 bytes.

Done, without errors.
Completed in 0.571s at Wed Jan 08 2014 11:33:07 GMT+0900 (JST) - Waiting...

と表示されます。無事uglify:destタスクが実行されました!

これで、わざわざコマンドを実行する手間から開放されます。便利!CoffeeScriptやLESSやSassなどのプリコンパイルが必要な言語にぴったりですね。

livereloadの実行

開発中のよくあるシーンに、ファイルを更新したらWebブラウザの再読み込みを行う、というのがありますが、watchタスクでそれを自動化することができます。

それを確かめるために、dest/index.htmlを適当に準備しておきましょう。

watchのlivereloadオプション有効化

watchにlivereloadオプションがあるので、それを有効化します。watchの記述を以下のようにしましょう。

watch:
  options: # 追加
    livereload: true #追加 
  scripts:
    files: ['src/js/*.js']
    tasks: ['uglify:dest']

これで、grunt watchとすると、対象ファイル変更時にWebブラウザへ更新依頼を出すサーバが立ち上がるようになります。が、Webブラウザ側でそれを受け取ることができませんので、その準備をしましょう。

Webブラウザへのlivereloadプラグインの追加

Webブラウザ側で更新依頼を受け取るようにするにはいくつか方法がありますが、楽なのはWebブラウザにliveleload対応プラグインを追加することです。How do I install and use the browser extensions? – LiveReload Help & Supportを参考に、WebブラウザへLiveReload用拡張を追加しましょう。

あとは、grunt watchを実行し、index.htmlをWebブラウザで開いてプラグインで追加されたボタンを押せば、準備完了です。

src/js/*.jsを変更して保存すると、ブラウザで再読み込みが発生するはず、です。

…しない人は、Webサーバを立ち上げずに、ローカルのindex.htmlを見ていないからかもしれません。

Webサーバ立ち上げ

ということで、せっかくなのでwatchついでに確認用のWebサーバを立ち上げておきましょう。これにはgrunt-contrib-connectを使います。

例のごとく

npm install grunt-contrib-connect --save-dev

して、

grunt.loadNpmTasks 'grunt-contrib-connect'

です。

3000番ポートでWebサーバが立ちあがるように、以下の記述を追加します。ドキュメントルートはdestにしています。

connect:
  server:
    options:
      port: 3000
      base: 'dest'

これでgrunt connectとすればサーバが立ち上がるのですが、せっかくなのでwatchとあわせてサーバが立ち上がるようにしましょう。

connectとwachtを実行するタスクを新しく定義します。名前はcwで。grunt.registerTask()を使います。

grunt.registerTask 'cw', ['connect', 'watch']

これでgrunt cwとすればサーバが立ち上がり、かつwatchの監視状態となります。

Webブラウザでlocalhost:3000にアクセスすればindex.htmlが開くはずですので、そこでlivereloadプラグインのボタンを押し、src/js/*.jsを更新すれば、ブラウザが再読込されるはず、です!

このlivereload、地味なようですがとても快適で、これ無しではやってられなくなります。再読み込みだけさせてタスクを起動しない、という使い方もしているくらいです。未体験な方はぜひお試しください。

次回こそは色々なタスクを…