2016-06-10 bouzuya/beater の browser support がだめだった
2016-06-09 の続き。bouzuya/beater の browser support を検証した。想定通りにいかず、大幅な見直しが必要になった。
beater の browser 対応、できてなかった
— bouzuya (@bouzuya) 2016年6月9日
substack/node-browserify / webpack/webpack でいろいろ試したが難しそうな状況だ。beater では test/*.js
相当の file 群を動的に require()
するつもりだったが簡単にはいかない。
まず browserify 。
browserify は require()
の中身が変数の場合は bundle.js
に含めてくれない。類似の issue は substack/node-browserify#377 にある。bundle.js
に含まれない点だけであれば substack/bulkify を使えば解決できる。bulkify は glob で bundle.js
に含めることはできるが、読み込む時点の制御はできない。
module ごとに require()
で読み込まれる module を変更することも意外と難しい。なので file (module name) を渡して、それを require()
するのは意外と難しい。独自の browserify transform を用意すれば理論上できそうだけど、利用側での問題が増えそうだ。
次に webpack 。
webpack は browserify の箇所で紹介した issue にもあるが context という考え方を持つ。これは require(expr)
/ require('pre-' + expr)
などの形に応じて directory をわりと乱暴に読み込むものだ。現状の問題としては余計なものを読み込みすぎて死ぬ。'fs'
や 'child_process'
に依存するものを読み込んでしまう。無理にでもこれを修正してみたが、今度は require()
の relative path の指定が思ったようにできず、苦しむ。つくったぼくでこれだ。beater の挙動を知らないと、なぜそんな設定をするのか、どのような path が正解なのか分からないはずだ。
上記に一日費やして、ぼくはひとつ結論に至った。browser で動的な require()
を前提にするのは避けるべきだ。ES Modules の観点でも静的解析できるほうが望ましい。
では ES Modules を前提にするとどうなるのか。いまの test()
を読み込む時点で実行する構造をとったときは entry point を各 file に置く必要が出てくる。files などの指定ではなくなってしまう。いま考えているのは test()
を Test
の定義として使い、実行の意味を奪う案だ。 const t1 = test(...); export default t1;
して Test
を export してもらう module をつくれば良い気がしている。考え方は大きく変わるが production code と同じ気持ちで test を書くことができるように思う。
もうすこし考える。