Firefox + Add-on SDK で 最終的に .xpi ファイルをビルドするには、
$ cfx xpi --pkgdir=/path/to/package --update-link=http://path/to/update-link --update-url=http://path/to/update-url
などとする。
cfx は、エクステンションを構成するファイルと、Add-on SDK が提供するライブラリをかき集めて .xpi ファイルを生成する。後者は、低位なライブラリ api-utils と高位な addon-kit の 2 種類あるのだが、addon-kit に関してはエクステンションが参照しているものだけを抽出して、.xpi のサイズの肥大化を防いでいる。なかなか賢いですね。
ただ、どうやってエクステンションが参照している addon-kit ライブラリを抜き出しているのかというと、$(addon-sdk)/python-lib/cuddlefish/manifest.py の中で、javascript ソースを正規表現レベルで走査している。
REQUIRE_RE = r"(?
という正規表現で、まさに grep している。javascript の構文解析をしているわけではない。
これがこうなっているのは、つまりこれでたいていの場合良いだろうということなんだと思うが、そうでもない場合もある。wasavi のパッケージは js ファイルを minify している。つまりパッケージ内の javascript ソースはものすごく長い 1 行のテキストなのだ。これが根本的な原因だと思うのだけど、参照しているライブラリの抜き出しがうまく行ったり行かなかったりする(たいていはうまく行かない)。
minify しなけりゃいいじゃんという気もするが、もしかしたら将来 closure compiler を使うかもしれないのでやっぱり cfx 側が変則的な javascript ソースにも対応してもらったほうがいいのではないかと思う。
とりあえずの回避策としてこうしている:
- エクステンションで参照しているすべてのライブラリを内部的に require するダミーのモジュールを作る。lib/dummy-require.js とか。
var self = require('self');
var pageMod = require('page-mod');
var tabs = require('tabs');
var simplePrefs = require('simple-prefs');
var clipboard = require('clipboard');
var timers = require('timers');var locale = require('api-utils/l10n/locale');
var xhr = require('api-utils/xhr');exports.hello = function () {
return 'it is dummy module';
}
このソースだけは、minify しない。 -
他の javascript ソースのどれか 1 つで、上記のソースを require する。ソースのできるだけ先頭の方がいいかもしれない。main.js あたりの先頭で:
if (typeof window == 'undefined') {
window = this;
window.jetpack = {};
require('./dummy-require');
}
のような感じ。require するだけで、別に何かに使ったりするわけではない。この状態で cfx xpi すると、必要なライブラリが正確に抜き出されるようだ。
うーんまあ割とどうでもいい tips だな!