gruntで自動化しているタスクが多くなり,いわゆる fat Gruntfile.js
になったのでリファクタリングした.
はじめに
プロジェクト開始初期のGrunfile.coffeeは【Grunt + Karma + Jasmine】CoffeeScriptの開発環境を構築するで書いたくらいの量だったが,約1, 2ヶ月で膨大になった.
grunt.loadNpmTasks 'grunt-contrib-coffee'
grunt.loadNpmTasks 'grunt-contrib-watch'
grunt.loadNpmTasks 'grunt-contrib-connect'
grunt.loadNpmTasks 'grunt-contrib-concat'
grunt.loadNpmTasks 'grunt-contrib-clean'
grunt.loadNpmTasks 'grunt-env'
grunt.loadNpmTasks 'grunt-open'
grunt.loadNpmTasks 'grunt-s3'
grunt.loadNpmTasks 'grunt-closure-compiler'
grunt.loadNpmTasks 'grunt-replace'
grunt.loadNpmTasks 'grunt-jsonlint'
grunt.loadNpmTasks 'grunt-jsbeautifier'
grunt.loadNpmTasks 'grunt-karma'
grunt.loadNpmTasks 'grunt-http'
読み込んでいるgruntライブラリは10数種類あり,それぞれの設定連想配列が列挙されている状態で,当時のGruntfile.coffeeは約300行弱あった.
リファクタに使用するライブラリ
load-grunt-configとjit-gruntを使用する.
npm install load-grunt-config --save-dev
npm install jit-grunt --save-dev
リファクタ前のGruntfile.coffee
Grunfile.coffeeに記述しているtask毎のconfig定義とtask alias定義を別ファイルに抽出する.
module.exports = (grunt)->
grunt.initConfig
watch:
coffee:
files: ['src/**/*.coffee']
tasks: 'coffee:app'
coffee:
app:
files: [
expand: true
cwd: 'src/'
src: ['**/*.coffee']
dest: 'src/js'
ext: '.js'
]
dist:
files: [
expand: true
cwd: 'src/'
src: ['**/_all.coffee']
dest: 'dist/'
ext: '.js'
]
concat:
dist:
src: ['src/hello.coffee', 'src/user.coffee', 'src/main.coffee']
dest: 'src/_all.coffee'
grunt.loadNpmTasks 'grunt-contrib-coffee'
grunt.loadNpmTasks 'grunt-contrib-watch'
grunt.loadNpmTasks 'grunt-contrib-concat'
grunt.registerTask 'default', ['watch']
grunt.registerTask 'publish', ['concat', 'coffee:dist']
task毎のconfig定義
task毎のconfig定義ファイルを/grunt/config/TASK-NAME.coffee
に分離する.
設定のトップレベルのキー名だった watch
, coffee
, concat
はファイル名に含め,module.exports =
以下には記述不要.
module.exports =
coffee:
files: ['src/**/*.coffee']
tasks: 'coffee:app'
module.exports =
app:
files: [
expand: true
cwd: 'src/'
src: ['**/*.coffee']
dest: 'src/js'
ext: '.js'
]
dist:
files: [
expand: true
cwd: 'src/'
src: ['**/_all.coffee']
dest: 'dist/'
ext: '.js'
]
module.exports =
dist:
src: ['src/hello.coffee', 'src/user.coffee', 'src/main.coffee']
dest: 'src/_all.coffee'
task alias毎の定義
task alias毎の定義ファイルをgrunt/tasks/ALIAS-NAME.coffee
を個別に作成する.
Gruntfile.coffee
に記述していたaliasの定義をほぼそのまま記述する.
module.exports = (grunt) ->
grunt.registerTask 'default',
[
'replace:cx-const'
'replace:media-html'
'coffee:display'
'coffee:redirect'
'cx_append:dispatcherExe'
'connect:server'
'open:server'
'watch:coffee'
]
リファクタ後のGrunfile.coffee
最後に元のGrunfile.coffeeの設定を書き換え,load-grunt-configとjitGruntの設定を記述する.
module.exports = (grunt)->
path = require('path')
require('load-grunt-config') grunt,
configPath: [
path.join(process.cwd(), 'grunt/config')
]
jitGrunt:
customTasksDir: 'grunt/tasks'
data:
KEY_NAME: 'Sample Data :)'
各configファイルでGrunfile.coffee内の値は,data.KEY_NAME
に指定すると,options.KEY_NAME
か<%= KEY_NAME %>
で参照できる.
module.exports = (grunt, options) ->
console.log(options.KEY_NAME) # Sample Data :)
その他やったこと
設定をローカル環境・開発環境・本番環境用に分けるために タスク x 3環境数分のJSONファイルを作成していた.
ファイルが分割されることで可読性が非常に悪くファイルを行ったり来たりでやりづらかった.
タスクごとに設定ファイルを分割したので,環境の分岐も含めて grunt/config/TAKS-NAME.coffee
に集約するようにしている.
replaceタスクはgruntの複雑さを増強していた.
値を差し替える箇所が複数ファイルにまたがっており,こちらもコードを追うのが困難だったので,置換される値を管理するクラスをつくり一箇所にまとめた.
まとめ
最終的にGruntfile.coffee
は30, 40行程度になり,タスク毎の設定も集約されたことで,gruntのメンテナンスもしやすくなった.
ただ設定量が多いことには代わりないので,別の方法も考えないと先がつらそう.