require されても exports しない
最近そういう書き方を思いついて実践している。
前提
- 100-200行程度のファイルの集合
- 10000行程度のスタンドアロンライブラリ
- node.js でテストして、最終的には結合してブラウザで使う
- 外部モジュールは使用しない
大雑把な説明
- ブラウザで require するの難しい。。
- require したくない。。
- require 消したいけど、消しにくい。。
- require で代入するから消しにくいのでは?
- 大きい名前空間をつくって各モジュールが名前空間を拡張すれば良いのでは?
- それで最後に依存関係に従って単純に貼り付けていけば良さそう
例
例えば color というモジュールはこういう感じで書く。 グローバル変数として名前空間があって、そこにモジュールを追加するだけで exports していない。
// color.js (function(namespace) { namespace.color = { fromRGB: function(r, g, b) { return [ r, g, b ]; } }; })(namespace); // namespace というのはグローバル変数
color モジュールの利用方法はこういう感じ。 require するけど変数には代入せずに、変わりに名前空間経由でモジュールを取得する。node.js では先にモジュールが読み込まれるので問題なく動くし、ブラウザ向けに結合するときは main.js より先に color.js を貼り付ければよい(その際 require は不要になるので行ごと消す)。要は require は依存関係の表明としてだけ使う。
// main.js (function(namespace) { require("./color"); // color.js が事前に読み込まれればこの行は不要になる var color = namespace.color; var white = color.fromRGB(255, 255, 255); namespace.main = { run: function() { console.log(white); } }; })(namespace);
最終的にライブラリとして外部に提供する部分。名前空間のうち特定の部分だけを外に出す。
// exports.js (function(namespace) { require("./main"); if (typeof module !== "undefined") { global.module.exports = namespace.main; } else { global.myApp = namespace.main; } })(namespace);
最終的にライブラリとしてパッケージするときに名前空間グローバル変数は消してしまう。
node.js の場合
global.namespace = {}; module.exports = require("./exports"); delete global.namespace;
ブラウザの場合
(function(global) { var namespace = {}; // color.js を貼り付け // main.js を貼り付け // exports.js を貼り付け // (各スクリプトを貼り付けるときに require の行を削除する) })(this);