いや、別に秘密でも何でもなく、ただ私が最近社内勉強会用に調べるまで知らなかっただけですが・・・。
grunt.initConfig()
で渡す Object がありますよね。Gruntfile.js のほとんどを占めるあの長大なオブジェクト。あまり良くわかっていなくても、ドキュメントやブログの例を真似すれば、どうにか Grunt を使うことはできます。
しかし、これってよく見ると、?なところがたくさんあります。
- options とかあるけど、options に入れるのと入れないの(src, dest など)は何が違うの?
- トップレベルに pkg とかタスク名じゃなさそうなものを入れてる例を見るけど?
-
grunt connect:server:keepalive
とか見るけどkeepalive
はどこから来たの?
Grunt の基本概念から調べつつ、これらの疑問に答えていきます。
普通のタスクとマルチタスク
Grunt のタスクには二種類あります。普通のタスクとマルチタスクです。マルチタスクは普通のタスクと何が違うかというと、ターゲットを持つところです。
ターゲットとは、その名の通りタスクの対象です。例えば、ファイルをコピーする copy
タスクがあり、js と css のファイルに対して実行したいとします。どちらかだけでも実行したいし、両方実行したい時もある。こういう場合、js
と css
をターゲットと呼びます。
大抵のプラグインが提供するタスクはマルチタスクです。普通のタスクは、自分で複数のタスクをまとめて一つのタスクにする際によく使われます。
設定を受け取るのは、マルチタスクだけです。
タスクはプラグインで定義されますが(もちろん自分で定義することもできます)、ターゲットは必ず自分で設定します。
grunt.initConfig({
copy: {
js: { src: 'app/js/**/*', dest: 'dist/js/' },
css: { src: 'app/css/**/*', dest: 'dist/css/' }
}
});
この場合、copy
という名前は決まっていますが、js
, css
は自分で好きな名前にすることができますし、さらに数を増やすこともできます。なお、ターゲットを入れ子にすることはできません。
マルチタスクの場合、タスク名だけを書いて実行すると、そのタスクのすべてのターゲットに対して処理を実行します。
grunt copy
もちろんターゲットを指定することもできます。
grunt copy:js
options とファイル設定
さて、タスクとターゲットの関係を整理すると、設定を書く対象は二種類であることがわかります。
- マルチタスク直下
- マルチタスクのターゲット
grunt.initConfig({
copy: {
/* 1. */
js: { /* 2. */ },
css: { /* 2. */ }
}
});
これらに書く設定は主に二種類です。
- options
- src, dest, files などのファイルパス関係
options は、タスクごとに固有のオプションです。マルチタスクではタスクレベルで指定することもできますし、ターゲットで指定すればタスクで指定した設定を上書きできます。
では、2. のファイルパス関係のオプションだけ何故特別なのかと言うと、Grunt はファイルを操作するものだからです。src, dest, files などなどいろいろありますが、どの書き方をしても Grunt の内部では files という、{ src: ['src1', 'src2', ...], dest: 'dest' }
な形式のマッピングの配列に変換されます。
テンプレート
公式サイトのサンプル Gruntfile でも、トップレベルに pkg というタスクではないものがありますよね。これは、実はテンプレートに使うものなのです。
Grunt は設定オブジェクト内の文字列をテンプレートとして補間してくれます。この際、トップレベルにあるプロパティが利用できるのです。
grunt.initConfig({
jsSrcDir: 'app/js',
jsDestDir: 'dist/js',
copy: {
js: {
src: '<%= jsSrcDir %>/**/*',
dest '<%= jsDestDir %>/'
}
}
});
どうしてタスクとごちゃ混ぜになるような設計にしたのかはわかりません。しかし、Grunt はこうなっているのです・・・。
ちなみに、タスクの設定プロパティもテンプレート内で利用できます。
grunt コマンドの謎
ここまででタスク、ターゲットについてわかってきたのではないかと思いますが、grunt connect:server:keepalive
とかよく目にしますよね。connect はタスク、server はターゲットだけど、keepalive は一体どこから来たの?ターゲットを入れ子にさせることはできなかったんじゃないの?という疑問が湧いてきます。
実はこの keepalive は、keepalive フラグが true だという意味なのです。
grunt.initConfig({
connect: {
server: {
options: {
keepalive: true
}
}
}
});
となっている時に grunt connect:server
したのと同様の効果を得られます。
grunt task:target:flag1:flag2:flag3
というような感じで、マルチタスクでは 3 つ目以降はフラグを表しているのです。これによって設定したターゲットをちょっと変えて実行することができるので、ほとんど同じだけど微妙に違うターゲットを複数用意するのを避けることができます。
しかし、この書き方ってちょっと変ですよね・・・。コロンで同じように区切られているものが、場所によって全然意味が違う・・・。しかし、そうなっているものは仕方ありません。あきらめて、チャンスがあればバシバシ使いましょう。
普通のタスクでは、2 つ目以降がタスクの関数の引数になるので、以下のようになります。
grunt task:arg1:arg2:arg3
おわり
これで Grunt に対するもやもやが少しは晴れたでしょうか?私は少しすっきりしました。どうしてこうなったか釈然としない部分はいくつかあるけど、これで楽しい Grunt ライフが送れる気がします。
おしまい。
2014.7.27 マルチタスクでないタスクが設定を受け取ると勘違いしていたので修正しました。実際は、設定を受け取るのはマルチタスクだけでした。