GruntのMultiタスクはまとめて実行モードだと書いた順に動くようなので、いちいちターゲット指定しなくても良さそうと勝手に考えていた。一応は本当に書いた順で実行されることが保証されてるのか気になってはいたので、ちゃんとソースを読んでみたところ、どうも保証されないようだ。

GruntのMultiタスクの一括実行Object.keysで返ってくる配列をforEach()してその中で各ターゲットを実行している。なので実行環境であるNode.jsというか、それで使われているV8がそれらをどう解釈するかに依存していることになる。そしてV8ではObject.keysで返ってくる配列(やfor...inの順番)が勝手にソートされるケースがあることもわかった。

タスクを実行すると設定されたデータを吐くだけのMultiタスクを例にする。

module.exports = function (grunt) {
  grunt.initConfig({
    order: {
      5: 5,
      1: 1,
      4: 4,
      3: 3,
      2: 2
    }
  });

  grunt.registerMultiTask('order', function () {
    grunt.log.writeln(this.data);
  });
};

以上のように数字をMultiタスクのターゲット名にしてしまうと書いた順にタスクが実行されない。

$ grunt order
Running "order:1" (order) task
1

Running "order:2" (order) task
2

Running "order:3" (order) task
3

Running "order:4" (order) task
4

Running "order:5" (order) task
5

Done, without errors.

あー……。


アルファベット始まりならば経験上は書いた順に実行されてたので、横着してconcatをチェインさせるのをターゲットを書く順番でごまかしてたけど止めた。タスクの実行順が重要な場合はMultiタスクの一括実行に期待せず、ひとつひとつターゲットを指定して書くようにしないと危険。