jit-grunt で grunt をキビキビ動作の高速化
Posted: Updated:
jit-grunt
この記事を見て知ったのだが、jit-grunt というプラグインが中々よい。Just In Time ということで、タスクのロードを loadNpmTasks
でまとめて最初にやる代わりに、各タスクの実行時までロードを遅延させるというもの。
npm の jit-grunt ページを見ると相当数がダウンロードされて利用者がいるようだが、検索するとあまり紹介されてないようだったので書いてみる。
効能
17個のタスクをロードしていた手元の環境に導入したところ、単純なタスクを実行した限りでは次のような実行時間の短縮が見られた。計測は例によって time-grunt だ。
Before
loading tasks で 625ms かかっていて、全体では 651ms を要した。
% grunt concat:lib (git)-[develop] Running "concat:lib" (concat) task File "temp/lib.js" created. Done, without errors. Execution Time loading tasks 625ms ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 96% concat:lib 25ms ▇▇ 4% Total 651ms
After
loading tasks で無駄にロードしなくなった結果、全体では 112ms に短縮された。
% grunt concat:lib (git)-[develop] Loading "grunt-contrib-concat" plugin Running "concat:lib" (concat) task File "temp/lib.js" created. Done, without errors. Execution Time loading tasks 91ms ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 81% loading grun...trib-concat 3ms ▇ 3% concat:lib 18ms ▇▇▇▇▇ 16% Total 112ms
条件と使用例
元々、次のような loadNpmTasks
列を成していた。
grunt.loadNpmTasks('grunt-styl'); grunt.loadNpmTasks('grunt-sass'); grunt.loadNpmTasks('grunt-contrib-csslint'); grunt.loadNpmTasks('grunt-contrib-clean'); grunt.loadNpmTasks('grunt-autoprefixer'); grunt.loadNpmTasks('grunt-csso'); grunt.loadNpmTasks('grunt-spritesmith'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks("grunt-jscs-checker"); grunt.loadNpmTasks('grunt-angular-templates'); grunt.loadNpmTasks('grunt-ng-annotate'); grunt.loadNpmTasks("grunt-contrib-concat"); grunt.loadNpmTasks("grunt-contrib-uglify"); grunt.loadNpmTasks("grunt-contrib-watch"); grunt.loadNpmTasks("grunt-nodemon"); grunt.loadNpmTasks("grunt-concurrent"); grunt.loadNpmTasks("grunt-bump");
これに jit-grunt
を次のように導入する。命名規則ベースでオートロードするので loadNpmTasks
は不要になる。
require('jit-grunt')(grunt, { sprite : 'grunt-spritesmith', ngtemplates : 'grunt-angular-templates', ngAnnotate : 'grunt-ng-annotate', jscs : 'grunt-jscs-checker' });
タスク名からパッケージ名を探索するときは次のようなルールに基づいている。このルールに当てはまらないパターンは、例に示したようなマッピングをしてやればいい。
- node_modules/grunt-contrib-task-name
- node_modules/grunt-task-name
- node_modules/task-name shootaroo/jit-grunt
賢明な諸氏ならお気づきだろうが
さきほどの 651ms → 112ms の短縮例はちょっとインチキだ。
使用するタスクが多くなれば、結局は多くのタスクをロードするので相応の時間がかかる。リリースビルドのような複合タスクを実行すれば、ほぼ全タスクが読まれるので、例に挙げたような性能改善は見られない。
とはいえ Grunt の初期化時間が短縮することで次のような効果は期待できる。
- Grunt 実行時の立ち上がりが速くなるので、体感速度が改善する
nodemon + watch
のような開発環境タスクの立ち上がりは単純に早くなるloadNpmTasks
を書く必要がなくなる(副次効果)
導入コストはかなり低いので、これらの利点に益を見いだせるなら試す価値はある。
Grunt 好きですよ
Grunt の性能改善系でいうと grunt-concurrent によるタスク並列化や、タスク自体を水平分割する grunt-parallelize もある。1〜2年前に発生した Grunt なプロジェクトも今や順調に肥大化している頃だろう。こういうライブラリを使って改善してみるには良い時期かもしれない。
ところで最近はビルド系の仕事は gulp
、開発環境系は npm run
でやるとコンパクトなのではと思っている。gulp ってほら、タスクランナーっていうかビルドシステムだから、役割を限定する上で筋を通しやすい感。(Gruntどこ行った)