ブラウザにCommonJSを簡単に提供するスニペット

CommonJS (+node.js 独自拡張)なモジュールをブラウザで読み込むにはいくつかの方法がある。たとえばbrowserbuildはまとめて1ファイルにしてくれるので、プロダクションコード用としてはとてもよい。一方でbrowserbuildは痒いところに手が届かないしデバッグも結合後のソースで行わなければならず、開発用としてはあまりよくない。
単純にモジュールをロードしたいだけなので、そのためのスニペットを書いてみた。

https://github.com/gfx/require-simple.js

// require-simple.js
function require(name) {
	"use strict";
	if(!require.modules) {
		require.modules = {};
	}
	if(require.modules[name]) {
		if(require.debug) {
			console.log("require: \"" + name + "\" is already loaded");
		}
		return require.modules[name].exports;
	}

	function findModule(paths, name) {
		for(var i = 0; i < paths.length; ++i) {
			var url = paths[i]+ "/" + name + ".js";

			var xhr = new XMLHttpRequest();
			xhr.open("GET", url, false);
			xhr.send(null);
			
			if(require.debug) {
				console.log("require: " + xhr.status + " " + url);
			}

			if(xhr.status === 200) {
				return xhr.responseText;
			}

			if(xhr.status !== 404 || (i+1) === paths.length) {
				throw new Error("Failed to load \"" + name + "\": " +
								xhr.status + " " + xhr.responseText);
			}
		}
	}

	var src = findModule(require.paths, name);

	/*jslint evil: true */
	var f = new Function("module", "exports", src);

	var module = require.modules[name] = {
		exports: {}
	};
	f(module, module.exports);
	return module.exports;
}
require.debug = false;
require.paths = ["."];

使い方:

<script src="require-simple.js"></script>
<script>
require.paths.unshift("assets/js");
var module = require("module");
</script>

node.jsの最新のパス指定(module.paths)には対応していないがとりあえずこれで十分だ。
なお、負荷のかかるサイトではこのスニペットを使うべきではない。browserbuildなどで結合したものを使ったほうがよい。