読者です 読者をやめる 読者になる 読者になる

音の鳴るブログ

鳴らないこともある

音楽用CoffeeScriptを作ろう (3) ビルドのはなし

昨日は実行環境について書いたのだけど、よくよく考えたら iframe の層は必要ないのでシンプルな構成に修正した。よく考えなくても不要だし、そもそも iframe をはさんだ理由はなんだというと(以下言い訳、略)

で、書き換えた構成が以下の図。 CoffeeCollider っていうのがユーザーが操作するインターフェースで、その他は案所良くやってくれる。そういう感じにした。

f:id:mohayonao:20131009094014p:plain

ちなみに最初にやろうとしていた iframe を使って安全に実行する話はここに書いてあった。


ここからはビルトなどの話。以下すべて Grunt でやっている。

コードは AMD(Asynchronous Module Definition) で書いている。ブラウザ向けの JavaScriptAMD で書いている場合 require.js が使われると思うんだけど、よく分からないし覚えるのも面倒そうだったので使わずに、DryIce というモジュールを使ってビルドしている。

このモジュールは InputStream みたいなところにコードの断片を投入していって、モジュール解決のコードを挿入してくれたり余分なコードを削除したりミニファイしたりできる。

こういう風に使う。

ここでやっているのは以下の作業。

  • ヘッダの挿入 (スコープを区切るやつ)
  • 偽require.js の挿入
  • ソースコードの挿入 (必要分だけ勝手にやってくれる)
  • 余分なコード (ソースファイルごとの "use strict"など ) の削除
  • フッターの挿入

ここで 偽require.js というのは、モジュール解決を行うための最低限のコードだけ書いてあるやつで、それにあわせて呼び出し側もちょっと修正している。

// 普通こうなるけど
define('cc/lang/lang-server',
       ['require', 'exports', 'module' , 'cc/cc', 'cc/lang/compiler'],
       function(require, exports, module) {
  "use strict";
});

// 依存の情報は不要なので削る (偽require.jsでは2つしか引数をとらない)
define('cc/lang/lang-server', function(require, exports, module) {
  // use strict も不要だから削る (ヘッダーに書いてあるので)
});

テストは Chai でやっている。ソースと同じ場所に *_test.js っていうテストファイルを作る。mocha で AMDモジュールのテストは面倒い感じだったのでタスクを自分で書いた。node.js で AMDモジュールをロードするのには AMD Loader というのが使えるのだけど、もとのやつは絶対パスのときに微妙な感じになるので少し修正して使っている。

ブラウザテストは行わない方針。音が出ているかどうかは書きようがないと思う。そのほかは計算ばかりなので node でのテストで充分。

他は watch して自動テスト → ビルドとか livereload とか travis に対応させたりとかしている。livereload は grunt-contrib-watch で対応したらしいので grunt-contrib-livereload からスイッチしたけど、Linuxで grunt して Windows の Chrome で開いているときに自動リロードしてくれなくて困っている。あと、関係ないけど Gruntfile.coffee って名前ダサいと思うので JavaScript で書いている。

結構色々やってると思ったけど160行くらいしかなかった。

演算子のオーバーロードの実装をしたので、次はそのことを書く。