Gruntのtaskの実行にかかる時間を劇的に短縮する方法
最近ではGrunt無しでのフロントエンド開発は考えられなくなってきた気がしますが、大抵taskを実行した際に結構時間がかかってしまいます。
Gruntの実行にかかる時間を減らすにはどうすれば良いのか調べてみたら、loadTasks as they are needed to speed up Grunt load time · Issue #975 · gruntjs/gruntのissueに方法がありました。
何に時間がかかっているか
taskを走らせた際、何で時間がかかっているのかをtime-gruntで確認してみると、実行しているtask自体ではなくnpmタスク(適切な表現かは分かりませんがGruntプラグインの事です。)の読み込みの方に時間がかかっている事が分かります。
loadNpmTasks()で2秒はかかっている状態
npmタスクの読み込みに何故時間がかかるかというと、Gruntではどのtaskを実行した場合でも全てのnpmタスクを読み込むことが原因のようです。
つまり、grunt-contrib-jshintだけが必要なlint
というtaskを定義してあったとして
$ grunt lint
と実行すると、Gruntfile
に記述されているlint
のtaskとは関係の無いgrunt-contrib-cssminだとかgrunt-browserifyといったnpmタスクまで全てロードしているということです。
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-cssmin'); // lintのtaskとは関係なくてもロードする
grunt.loadNpmTasks('grunt-browserify'); // lintのtaskとは関係なくてもロードする
実行するtaskに必要なプラグインのみをロードする
maslen氏のコメントの方法を取ると、npmタスクの読み込みは実行するtaskのコールバック関数で行われるようになるので、そのtaskに必要なものだけを読み込むことが可能になります。
全てのnpmタスクを読み込まなくなるので、ロードにかかる時間は必要なnpmタスクだけに限定されます。
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-browserify');
grunt.registerTask('lint', ['jshint']);
という従来の形ではなく、
grunt.registerTask('lint', [], function () {
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.task.run('jshint');
});
とすれば、ロードにかかっていた時間は劇的に短縮することが出来ます。
2秒かかっていたloadNpmTasks()が130ミリ秒にまで短縮されています
記述が冗長になってしまう点はあるものの、パフォーマンスの点ではかなり改善できるので、Gruntのtaskの実行にかかる時間を短縮したい場合には試してみると良いかもしれません。