27
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Grunt の設定オブジェクトの秘密

Last updated at Posted at 2014-07-25

いや、別に秘密でも何でもなく、ただ私が最近社内勉強会用に調べるまで知らなかっただけですが・・・。

grunt.initConfig() で渡す Object がありますよね。Gruntfile.js のほとんどを占めるあの長大なオブジェクト。あまり良くわかっていなくても、ドキュメントやブログの例を真似すれば、どうにか Grunt を使うことはできます。

しかし、これってよく見ると、?なところがたくさんあります。

  • options とかあるけど、options に入れるのと入れないの(src, dest など)は何が違うの?
  • トップレベルに pkg とかタスク名じゃなさそうなものを入れてる例を見るけど?
  • grunt connect:server:keepalive とか見るけど keepalive はどこから来たの?

Grunt の基本概念から調べつつ、これらの疑問に答えていきます。

普通のタスクとマルチタスク

Grunt のタスクには二種類あります。普通のタスクとマルチタスクです。マルチタスクは普通のタスクと何が違うかというと、ターゲットを持つところです。

ターゲットとは、その名の通りタスクの対象です。例えば、ファイルをコピーする copy タスクがあり、js と css のファイルに対して実行したいとします。どちらかだけでも実行したいし、両方実行したい時もある。こういう場合、jscss をターゲットと呼びます。

大抵のプラグインが提供するタスクはマルチタスクです。普通のタスクは、自分で複数のタスクをまとめて一つのタスクにする際によく使われます。

設定を受け取るのは、マルチタスクだけです。

タスクはプラグインで定義されますが(もちろん自分で定義することもできます)、ターゲットは必ず自分で設定します。

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 とファイル設定

さて、タスクとターゲットの関係を整理すると、設定を書く対象は二種類であることがわかります。

  1. マルチタスク直下
  2. マルチタスクのターゲット
grunt.initConfig({
  copy: {
    /* 1. */
    js: { /* 2. */ },
    css: { /* 2. */ }
  }
});

これらに書く設定は主に二種類です。

  1. options
  2. 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 マルチタスクでないタスクが設定を受け取ると勘違いしていたので修正しました。実際は、設定を受け取るのはマルチタスクだけでした。

27
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?