web-dev-qa-db-ja.com

Grunt.jsで、複数のファイルを監視し、変更されたファイルでのみタスクを実行するにはどうすればよいですか?

grunt の使用方法を学習する際に、私は簡単なコーヒースクリプトウォッチャー/コンパイラを作成しようとしています。問題は、watchタスクに複数のファイルを監視するように指示し、1つの変更があれば、すべてのファイルをcoffeeコマンドに渡すことです。つまり、1つのファイルを変更すると、srcパターンに一致するすべてのファイルallが再コンパイルされます。代わりに、srcパターンに一致する変更された単一のファイルのみを再コンパイルします。

grunt.jsは次のとおりです。

module.exports = function(grunt) {
  grunt.initConfig({
    coffee: {
      app: {
        src: ['test/cases/controller/*.coffee'],
        dest: 'tmp',
        options: {
          bare: true,
          preserve_dirs: true
        }
      }
    },
    watch: {
      files: ['<config:coffee.app.src>'],
      tasks: ['coffee:app']
    }
  });

  grunt.loadNpmTasks('grunt-coffee');
  grunt.registerTask('default', 'coffee');
};

これは grunt-coffee を使用しています。これは基本的には https://Gist.github.com/2373159 です。

grunt watchを実行し、test/cases/controller/*.coffeeにファイルを保存すると、一致するファイルをallコンパイルします(tmp/*に入れます) 。

代わりにのみchangedファイルをgruntを使用してコンパイルしますか?

43
Lance Pollard

今後の(そして現在開発中の)v0.4.0a gruntには grunt.file.watchFiles オブジェクトがあり、この目的のために明示的に設計されています。 grunt-coffeeプラグインは、この機能のサポートを既に追加している可能性がありますが、わかりません。

いずれにせよ、プロジェクトで開発中バージョンのgruntを試してみたい場合は、 開発中機能 'X'をいつ使用できますか? FAQエントリ。

15

少ないファイルをコンパイルするときにこれが機能するようになりました。 coffeescriptプラグインを使用してgitを動作させるには、この構成を少し混乱させる必要があります。関心のある部分はgrunt.event.on('watch', ...)です。このイベントハンドラーでは、lessコマンドのfilesプロパティを更新して、変更されたファイルのみを含めるようにします。

path = require('path');

module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({

    pkg: grunt.file.readJSON('package.json'),

    less: {
      development: {
        options: {
          paths: ["./library/less"],
        },
        files: [
          { src: "./library/less/bootstrap.less", dest: "./library/css/bootstrap.css"},
          { src: "./library/less/app.less", dest: "./library/css/app.css"}
        ]
      }
    },

    watch: {
      styles: {
        files: "./library/less/*",
        tasks: ["less"],
        options: {
          nospawn: true,
        },
      },
    },
  });

  // Event handling
  grunt.event.on('watch', function(action, filepath){
    // Update the config to only build the changed less file.
    grunt.config(['less', 'development', 'files'], [
      {src: filepath, dest: './library/css/' + path.basename(filepath, '.less') + '.css'}
    ]);
  });

  // Load the plugins
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-watch');

  // Tasks
  grunt.registerTask('default', ['watch']);
};
8
blachniet

これらの答えはどれも私にとってはうまくいきませんでした。誰かが興味を持っている場合の私の解決策は次のとおりです(この質問への回答が少し遅れていることは知っています)。

https://Gist.github.com/ryansmith94/8569178

4
Ryan Smith

https://github.com/tschaub/grunt-newer は、同様のタスクとまったく同じように見えます。

新しいファイルでのみ実行するようにGruntタスクを構成します。

概要:新しいタスクは、a)destファイルより新しい、またはb)最後に成功した実行(destファイルがない場合)より新しいsrcファイルで実行するように別のタスクを構成します。例と詳細については、以下を参照してください。

任意のタスクに簡単に追加できます。あなたの場合:

  grunt.loadNpmTasks('grunt-newer');
  grunt.registerTask('default', 'newer:coffee');
3
Lajos Veres

この issue では、Kyle Robinsonはwatcheventの使用を提案しています。監視タスクのnospawnプロパティをtrueに設定して動作させることが非常に重要です。私は彼のソリューションを修正して、タスクを選択的に実行しました。

grunt.event.on('watch', function(action, filepath) {
    if (minimatch(filepath, grunt.config('watch.stylesheets.files'))) {
        grunt.config('compass.dist.options.specify', [filepath]);
    }

    if (minimatch(filepath, grunt.config('watch.scripts.files'))) {
        var uglifySrc = filepath.replace(grunt.config('uglify.dist.cwd'), '');
        grunt.config('jshint.dist.src', [filepath]);
        grunt.config('uglify.dist.src', [uglifySrc]);
    }
});

完全なソリューションは次のとおりです。 https://Gist.github.com/luissquall/5408257

3
luissquall

タスクgrunt-contrib-watchはこれをサポートするようになりました。

https://npmjs.org/package/grunt-contrib-watch ->「必要に応じてファイルをコンパイルする」を探す

grunt.initConfig({
  watch: {
    scripts: {
      files: ['lib/*.js'],
      tasks: ['jshint'],
      options: {
        nospawn: true,
      },
    },
  },
  jshint: {
    all: ['lib/*.js'],
  },
});

// on watch events configure jshint:all to only run on changed file
grunt.event.on('watch', function(action, filepath) {
  grunt.config(['jshint', 'all'], filepath);
});

これにより、何かが変更されるたびにタスクがすべてのファイルをコンパイルしないようにする必要があります。

2
smets.kevin

Grunt 0.4には、より多くのタスクが追加されました

例を挙げましょう!

watch: {
    package1: {
        files: [
            './modules/package1/**/*.coffee'
        ],
        tasks: ['coffee:package3']
    },
    package2: {
        files: [
            './test_packages/package2/**/*.coffee'
        ],
        tasks: ['coffee:package3']
    },
    package3: {
        files: [
            './test_packages/package3/**/*.coffee'
        ],
        tasks: ['coffee:package3']
    },
}

これらの監視タスクをすべて実行するには、単にgrunt.registerTask( 'default'、['myInitialBuild'、 'watch']);を実行します。

ここで、myInitialBuildは初期ビルド(すべてのファイル)であり、その後、各パッケージを監視します。実際には、すべてのファイルに対してこれを行うことができますが、それは下手に聞こえます。

2
Michael