たまには素でJavaScriptファイルをビルドすることも考えないと頭がダメになりそう。他にgulpとかでかすぎるし、npm run-script
だけでいけるいけるみたいな話を先行者以外からも聞くようになったので、そっちに比重を移すことも視野に入れたいとか。僕はビルド・ツールをnpm run-script
で薄くラップする手法というのが現実的だと考えてて、それを確認したいというのもあった。
依存はnpmやBowerで解決している前提で、自前で書いたものを最小化し、依存と連結するようなものを想定しておく。つまり、
をbuild/js/main.min.js
へとビルドするくらいにしておく。
#!/usr/bin/env node
'use strict';
var async = require('async');
var fs = require('fs-extra');
var path = require('path');
var uglifyjs = require('uglify-js');
async.waterfall([
function (next) {
fs.remove('tmp/', function (err) {
next(err);
});
},
function (next) {
fs.remove('build/', function (err) {
next(err);
});
},
function (next) {
fs.ensureDir('tmp/', function (err) {
next(err);
});
},
function (next) {
fs.ensureDir('tmp/js/', function (err) {
next(err);
});
},
function (next) {
fs.readFile('src/js/bar.js', 'utf8', function (err, data) {
next(err, data);
});
},
function (js, next) {
fs.readFile('src/js/baz.js', 'utf8', function (err, data) {
next(err, js + ';' + data);
});
},
function (js, next) {
try {
next(null, uglifyjs.minify(js, {
fromString: true
}).code);
} catch (err) {
next(err);
}
},
function (js, next) {
fs.readFile(
path.join(
__dirname,
'node_modules',
'foo',
'dist',
'foo.min.js'
),
'utf8',
function (err, data) {
next(err, data + ';' + js);
}
);
},
function (js, next) {
fs.writeFile('tmp/js/main.min.js', js, function (err) {
next(err);
});
},
function (next) {
fs.move('tmp/', 'build/', function (err) {
next(err);
});
}
],
function (err) {
if (err) {
throw err;
}
});
コード自体は簡単でわかりやすい。手軽なのでasyn.waterfall()
でフローを制御。Streamじゃないけど、中間ファイルを吐かないのでGruntよりは速い。テキトーに書かれたモジュールもtry...catch
しつつ流せるとか気軽に書ける。ファイルの保証やディレクトリの削除などはfs-extra
パッケージに頼ればこんなもので済んだ。
……でも長い。これでもfs-extra
パッケージのおかげで短くなってる。読み込みと連結をまとめたりとかでもっと短くできるけど、そこを抽象化するとストレートに書けるという長所が無くなっちゃう。async
の代わりにPromisifyするともうちょっと楽だけど、それほど劇的でもない。
ビルド・ツールのキモはやはりグロブを使った抽象化を提供してくれるあたりにあり、そこを毎回自前でどうにかするのは面倒すぎる。Gruntやgulpのような巨大な依存を減らせることは確かだけど、その代わりに小さな依存が増えるので、あんまり変わらない。こういうのを書くためのパッケージをセットにしたメタ・パッケージみたいなのがあればまた少し話が変わる……かなー?
こういうのを抽象化して引数で入力と出力を指定して終わりというパッケージがあっても面白そうだけど、それだとGruntとあんまり変わらないっぽい。Gruntfile.js
を書く代わりにpackage.json
で複雑な引数を書くわけだし。
つまりmake
はありだけど、npm run-script
はなしかなーという感じになった。引数取れるようになったのでnpm run-script
でいけるいけるとか言ってる人の話はじっくりと聞いて、本気でそれだけで済むと言っていたら聞き流した方が良さそう。