2013-02-03

makefileを廃絶してgruntを使う

JavaScriptを使った開発で必要となるconcat, minify, lint, test といったタスクを動かすのに使うツール、最近はgruntをよく見かけるのでオレオレmakefileから移行してみた。

既存のmakefileは以下の通り。makefile + makeターゲットから呼び出される各種タスクに対応した処理を行なうプログラムという構成。make minifyと打てば圧縮版のファイルを生成、make testと打てばテストが実行される寸法だ、圧縮にはuglify.js, lintにはjshint、全てnodeモジュールを使っているのでそのまま移行できるはず。concatにはmuというテンプレートエンジンを使っていた。

SRC_DIR = src
.PHONY: test
FILES = ${SRC_DIR}/api.js ${SRC_DIR}/trap.js ${SRC_DIR}/typechecker.js ${SRC_DIR}/all.js
CONCAT_FILE = struct.js
MINIFY_FILE = struct.min.js
default_target: all
TARGET = clean concat minify
all: $(TARGET)
setup_build_environment:
npm install
clean:
-rm -f ${CONCAT_FILE}
-rm -f ${MINIFY_FILE}
concat: clean ${FILES}
@echo "** Start concat source files"
node build/concat.js > ${CONCAT_FILE}
check: concat
@echo "** Start check source files by jshint"
node build/check.js < ${CONCAT_FILE}
minify: check
@echo "** Start minify concat file"
./node_modules/uglify-js/bin/uglifyjs --unsafe < ${CONCAT_FILE} > ${MINIFY_FILE}
@echo "Created ${MINIFY_FILE}"
test:
@echo "** Start tests"
node --harmony ./node_modules/jasmine-node/bin/jasmine-node test
view raw makefile hosted with ❤ by GitHub

makefileからの移行

まず、gruntの制御に必要なgrunt.jsファイルは grunt init:gruntfile して生成する。concat, lint, minify がビルトインタスクとして既に存在しているのがわかる。それらの箇所を修正して対象ファイルを指定する。

gruntからシェルコマンドの実行

最初に困ったのが、gruntから npm test を実行したいが、シェルのコマンドを実行する方法がデフォルトでは存在しない事。そこで grunt-exec というgruntプラグインを発見したので利用した。最終的に次のgrunt.jsになった。

module.exports = function(grunt) {
grunt.initConfig({
pkg: '<json:package.json>',
meta: {
name: 'Struct.js'
},
exec: {
run_nodejs_test: {
command: 'npm test',
stdout: true
}
},
lint: {
files: ['grunt.js', 'src/**/*.js']
},
concat: {
dist: {
src: [
'<file_template:src/header.txt>',
'<file_strip_banner:src/prepare.js>',
'<file_strip_banner:src/typecheck.js>',
'<file_strip_banner:src/handlermaker.js>',
'<file_strip_banner:src/api.js>'
],
dest: 'struct.js'
}
},
min: {
dist: {
src: [
'<config:concat.dist.dest>'
],
dest: 'struct.min.js'
}
},
watch: {
files: '<config:lint.files>',
tasks: 'lint qunit'
},
jshint: {
options: {
curly: true,
eqeqeq: true,
immed: true,
latedef: true,
newcap: true,
noarg: true,
sub: true,
undef: true,
boss: true,
eqnull: true,
browser: true
},
globals: {
'global': true,
'module': true,
'console': true,
'Proxy': true
}
},
uglify: {}
});
// Default task.
grunt.registerTask('test', 'exec');
grunt.registerTask('default', 'lint concat test min');
// Plugins
grunt.loadNpmTasks('grunt-exec');
};
view raw grunt.js hosted with ❤ by GitHub
grunt testでテストが実行されるし、grunt watchしてコードを編集すれば勝手にlint, concat, testしてくれるので移行はOK。 古参JSerであればRailsにアセットパイプラインが導入される前から、それ相当の機能を持つ秘伝のタレ的なMakefileやRakefileを使ってきたとは思うが、gruntはプラグインという形でタスクを共有できるので新規プロジェクトで使ってみるメリットは十分ある。少なくともCakefileよりはイケている。ライブラリでは無くWebアプリケーションの開発であればgruntを利用したyeomanの方が良さげ。