2013-12-08

browserify を使い始めるためのファーストステップ 2013 冬

browserify は、ブラウザ JavaScript のためのコードを、Node スタイルのコード(Node 向けの JavaScript コードを書いているかのような形)で記述しておいて、ブラウザ上で利用できるような Javascript コードとして出力してくれるツール。
require() で利用しているモジュール群をすべてアナライズして、それらモジュールコードまですべて都合よい形で同梱してくれる。

リリース当初(3年くらい前)は Node で HTTP サーバを建ててブラウザ用 Javascript コードを返すような仕掛けから始まったはずで、そこから静的ファイルを出力する仕組みが追加されて、現在ではむしろ後者の方がメイン扱いになっている感じになっている。
そうなった背景として、Grunt の登場でその辺りの機能が有効的に参照利用できるようになったり、実際に Grunt を使ってのビルド環境がカジュアルに行われるような土壌が出来上がったからというのが大きいのかもしれない。

今から browserify の利用を始めるべく browserify 側の情報をみても、低レベルなところが中心で戸惑ってしまい躊躇してしまうかもしれない。どんなものかを知るために動かすならば、簡単に利用できる Grunt 経由側のものを知ってしまったほうがよいと思う。
ということで、簡単なサンプルを紹介。

今回利用するファイルとツリーの状態は以下の通り。

@ /
├─ Gruntfile.js
├─ package.json
├─ index.html
├─ main.js
└┬ lib/
├─ foo.js
└┬ bar/
└─ baz.js
view raw tree hosted with ❤ by GitHub


------------

まずは環境作りのための package.json。
モジュールは grunt と、grunt で browserify するための grunt-browserify。
あとはサンプル用スクリプトで使うモジュール例として async.js を指定している。

{
"private": true,
"dependencies": {
"async": "0.2.9"
},
"devDependencies": {
"grunt": "~0.4",
"grunt-browserify": "*"
},
"optionalDependencies": {},
"engines": {
"node": ">= 0.8.0"
}
}
view raw package.json hosted with ❤ by GitHub


記述後、npm install を実行する。

続いて、ブラウザ上で動作させるための JavaScript コードを Node スタイルで記述。
以下のサンプルでは、core モジュールと npm で入れたモジュールを require() で利用しつつ、エントリポイントとなるスクリプトから自前のファイルを require() して読み込んでいる。

var foo = require('./lib/foo.js');
var content = document.getElementById('content');
foo.run([ 3, 10, "foo", "bar", 42 ], function (err, results) {
if (err) throw err;
results.forEach(function (r) {
content.innerHTML += ' ' + r;
});
});
view raw main.js hosted with ❤ by GitHub

var async = require('async');
var baz = require('./bar/baz');
exports.run = function (values, callback) {
async.map(values, function (v, next) {
next(null, baz(v));
}, callback);
};
view raw foo.js hosted with ❤ by GitHub

var format = require('util').format;
module.exports = function (v) {
if (typeof v === "string") {
return format('%s OK.', v);
} else if (typeof v === "number") {
return v * 10;
} else {
return v;
}
};
view raw baz.js hosted with ❤ by GitHub


browserify を実行する Gruntfile.js を用意。

module.exports = function(grunt) {
var pkg = grunt.file.readJSON('package.json');
grunt.initConfig({
browserify: {
dist: {
src: 'main.js',
dest: 'build.js'
}
}
});
Object.keys(pkg.devDependencies).forEach(function (devDependency) {
if (devDependency.match(/^grunt\-/)) {
grunt.loadNpmTasks(devDependency);
}
});
grunt.registerTask('default', [ 'browserify' ]);
};
view raw Gruntfile.js hosted with ❤ by GitHub


grunt を実行すると、build.js が出力される。
中身を覗いてみると、browserify が頑張って構築してくれたブラウザ用 JavaScript コードとして、先ほど自分で記述したコードやアナライズした結果同梱する必要ありと判断された util.fomat や async.js などが含まれている。

適当な HTML ファイルを用意して、この build.js を script タグで読み込むようにする。

<html>
<head>
</head>
<body>
<div id="content"></div>
<script src="build.js"></script>
</body>
</html>
view raw index.html hosted with ❤ by GitHub


実行デモ


先ほど browserify v3 がリリースされたばかりで、記念的な感じで。

上記例は v2 系を動かした結果 (grunt-browserify がまだ v2 を使うため)  なものの、恐らくただ単純に使う分には v3 以降も違いなくいけるんじゃないかと(個人的な期待)。