YeomanでAngularJSしてCoffeeScriptにしてみた。っていうかGrunt最強って話

JavaScript FrameworkならBackboneでしょ。
と勝手に思い込んでそればっか使ってきたボクですが、年初にheavenshellかどっぺちゃんとで飲んだ時にviewが重くなるよね―とか話してたしかにそれ悩みだよなと思った。

そんときAngularJSってどうなんだろうねーって話にちょっとなって、そんときからangularいつかやってみようと思いつつ仕事で忙殺されてたんだけど、今日何気にSNSで「AngularJSに仮入信してみる」ってつぶやいたらGoogleの人にいいね!してもらってちょっと上がった。

さらに都合のいいことに外出で2時間程度電車に乗ってヒマな時間ができたので、車中でAngularの洗礼を受けてみようとPCを開いた次第。ちなみに途中で酔いました。以前新幹線で思い知ったのだけど懲りてなかった。電車でコーディングは控えましょう。特に自分。

さて、AngularJS。GoogleJavaScript Frameworkである。どんなものかというのはググればいいので省略するとして、ボクがangular気になってる点というのはDIパターンを採用している点。クラス間の依存性が疎になるほうがコード量が増えていってもテストしやすくなるんじゃね?と。

Backboneだと依存性強く書けちゃうので、メンテナンスしていくとどうしてもそうなって、特にViewにしわ寄せがいってテストとか書きづらくなる。まあ自分の実力不足もあるんだろうけど、そういう傾向あるねって年初の会でも話題になってた。まあそういうのをangularなら小マシになるかもなと期待してやってみるわけです。

まあいっぺん書いてみようと。angularはまったく知らないので本家のチュートリアル見ながらイチからです。しかし本家からzipをダウンロードはしない。最近は何をつくるにもyeomanから始めることになっているのでyeomanからangularのプロジェクトを作成する。

$ yeoman init angular

こっから勉強していくことにした。ちょいとチュートリアルとはファイル構成が違うけど、まあわかるからいいや。つーかyeoman便利。

yeomanが吐いてくれるJSは app/scripts/app.js と app/scripts/controllers/main.js。app.jsをルーターにしてcontrollers/以下にコントローラーを置いていく感じ。index.htmlではapp.js, main.jsの順に読み込んでる。OKこれをcoffeeに訳す。 app.coffeeとmain.coffeeはこんな感じにした。

あとはこのまま yeoman server で完成!と思ったらそうはいかない。他のframeworkよろしくangulerもオブジェクトを各クラス間で使いまわす。しかしCoffeeScriptはコンパイル時にデフォルトでファイルごとのソースを匿名関数でラッピング(即時関数っていうんだっけ?)する。

上記のソースの場合、app.coffeeで生成した angulerApp を main.coffeeで呼び出してcontrollerを登録しているのだけど、このままコンパイルすると出力されるapp.js と main.jsとでは名前空間が異なるので、main.jsでangulerAppなんてないよ、とエラーになるわけである。

coffeescriptで複数のファイルでアプリを書く、例えば1クラス1ファイルみたいにするとすごくキレイに書けるんだけど、コンパイル時に上記のようになるのでそのままじゃ動かない。こういうときどうするかというと、coffeeコマンドで --join オプションを使って各ファイルを結合したり、 --bare オプションで即時関数化を無効化して各ファイルをグローバルで動くようにする。どちらを選ぶかはケースによって判断するのがいい。

yeomanではcoffeeのコンパイルをGruntに一任している。Gruntのcoffeeプラグインをみてみると、bareオプションが使えるみたいなので、yeoman angulerではbareでコンパイルするのが効率良さそうだ。ということで、プロジェクト直下のGruntfile.jsを以下のようにする。

29〜32行目にoptionsブロックを追加し、bareをtrueに設定。これでcoffeeのコンパイル時にグローバルなjsを吐いてくれるようになる。これで yeoman serverを実行すると正常にアプリケーションが起動する。

f:id:bathtimefish:20130302101349p:plain

実はボクはこのときまでGruntでbareオプションが設定できるのを知らなくて、今までGruntで複数ファイルを連結するときはconcatで連結してからコンパイルという設定をやってきた。こんなふうに。これはこれでアリなんだけど、ファイルが増えるたびにGruntfileを更新しないといけなくてもっといい方法ないかなーと思ってたら上記のようなカンタンな方法があったわけですね。ドキュメント読まな。。orz

まあ何はともあれyeoman angulerでも気持よくcoffeeで書けそうになったのでちょっとAngulerJSを勉強してみますわ―という本日からしばらくになりそうです。つーかいつも思うけどGrunt便利すぎ最強。