自動的にCoffeeScriptをコンパイルする
CoffeeScriptの問題はあなたとJavaScriptの間に他のレイヤーを増やすことです。CoffeeScriptのファイルが変更され、古くなる度に手動でコンパイルせねばなりません。幸いなことにCoffeeScriptはいくつかのコンパイル代替形態を持っており、開発サイクルをいくらかスムーズにすることが可能です。
最初の章で説明したとおり、CoffeeScriptはcoffee
コマンドを用いてコンパイル可能です。
coffee --compile --output lib src
上の例では全てのsrc
ディレクトリ内の.coffee
ファイルはコンパイルされ、lib
ディレクトリに個々の出力が置かれます。これを呼ぶだけでもちょっと面倒かもしれません。自動化する方法を探しましょう。
Cake
CakeはとてもシンプルなビルドシステムでMake や Rakeに倣っています。このライブラリはcoffee-script
のnpmパッケージにバンドルされておりcake
という名前のコマンドで利用可能です。
Cakefile
と呼ばれるファイルにCoffeeScriptを用いることでタスクを定義できます。cake [task] [options]
を同じディレクトリで実行することにより、Cakeがそれらのタスクを取り上げ、起動します。全てのタスクとオプションのリストを表示するにはただcake
と入力します。
タスクはtask()
関数を用いて定義します。名前と任意で詳細説明とコールバック関数を与えます。例としてCakefile
という名のファイルを作り、lib
とsrc
という2つのディレクトリを作成してください。Cakefile
には次の内容を追加します。
fs = require 'fs'
{print} = require 'sys'
{spawn} = require 'child_process'
build = (callback) ->
coffee = spawn 'coffee', ['-c', '-o', 'lib', 'src']
coffee.stderr.on 'data', (data) ->
process.stderr.write data.toString()
coffee.stdout.on 'data', (data) ->
print data.toString()
coffee.on 'exit', (code) ->
callback?() if code is 0
task 'build', 'Build lib/ from src/', ->
build()
上の例ではbuild
というタスクを定義しました。cake build
で実行できます。これは先の例と同じコマンドを実行しsrc
にあるCoffeeScriptファイルを全てJavaScriptにコンパイルし、lib
に置きます。これでHTMLファイルから通常どおりにlib
の中にあるJavaScriptファイルを参照できます。
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<script src="lib/app.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
</body>
</html>
これではまだcake build
をCoffeeScriptのコードを変更するたびに手動で実行せねばなりません。理想からは遠いです。幸運なことに、coffee
コマンドは別のオプションがあります。--watch
はコマンドにディレクトリに対して変更を見張るように指示し、必要な場合にはリコンパイルします。それを用いて別のタスクを定義しましょう。
task 'watch', 'Watch src/ for changes', ->
coffee = spawn 'coffee', ['-w', '-c', '-o', 'lib', 'src']
coffee.stderr.on 'data', (data) ->
process.stderr.write data.toString()
coffee.stdout.on 'data', (data) ->
print data.toString()
もしあるタスクが別のタスクに依存する場合、別のタスクをinvoke(name)
を用いて実行することが可能です。Cakefile
にもう一つ便利なタスクを追加しましょう。index.html
を開きソースの変更の見張りを開始します。
task 'open', 'Open index.html', ->
# 最初に開いて、次に見張る
spawn 'open', 'index.html'
invoke 'watch'
タスクにはoption()
関数を用いてオプションを定義することが可能です。引数として短かい名前、長い名前、そして説明を渡せます。
option '-o', '--output [DIR]', 'output dir'
task 'build', 'Build lib/ from src/', ->
# Now we have access to a `options` object
coffee = spawn 'coffee', ['-c', '-o', options.output or 'lib', 'src']
coffee.stderr.on 'data', (data) ->
process.stderr.write data.toString()
coffee.stdout.on 'data', (data) ->
print data.toString()
ご覧のとおり、タスクコンテキストがユーザが指定した任意のデータを持つoptions
オブジェクトにアクセス可能となりました。もしcake
を引数無しで実行した場合、全てのタスクと引数がリストされます。
Cakeは、bashやMakeファイルを用いずにCoffeeScriptをコンパイルするような一般的なタスクを自動化する、素晴しい方法です。Cakeのソースを読むことにはとても価値があります。CoffeeScriptの表現力の素晴しい例です。コードにはコメントが添えられて美しくドキュメント化されています。
サーバサイドサポート
CakeをCoffeeScriptのコンパイルに用いるのは静的なサイトでは問題ありません。しかし動的なサイトではCoffeeScriptのコンパイルをリクエスト/レスポンスサイクルに統合せねばなりません。色々な統合ソリューションが人気の高いバックエンドの言語とフレームワークに対して既に存在します。例えばRails や Djangoです。
Rails3.1ではCoffeeScriptのサポートはSprockets & the asset pipelineを通して提供されます。CoffeeScriptファイルをapp/assets/javascripts
の下に追いてください。Railsは十分に賢くリクエストを受けたときに事前にコンパイルします。JavaScriptとCoffeeScriptのファイルは特別なコメントの指示を用いて包まれ、連結されます。これは1つのリクエストでアプリケーションの全てのJavaScriptを取得することが可能であることを意味します。運用時にはRailsはコンパイル結果をディスクに記録し、キャッシュされ、高速なサービスを保障します。
他のRubyの選択肢にはrackサーバがあります。例えば37signalのPow や Joshua Peek の Nackがあります。両者共、もしあなたのアプリケーションがRailsの他の機能や関連するオーバーヘッドを必要としないのなら最高にお勧めです。
DjangoもまたCoffeeScriptのサポートを特別なテンプレートタグを通して行います。インラインコードでも外部ファイルでも利用可能です。
RubyとPythonは共にCoffeeScriptをコンパイルする時、NodeやCoffeeScriptのライブラリへパイプから出力します。そのためそれらを開発の間にインストールしなければなりません。もしNodeを直接、あなたのサイトのバックエンドとして使用している場合、CoffeeScriptの統合はよりシンプルで、バックエンドとフロントエンドコードの両方で使用可能です。このことについては次の章でより詳しく説明します。Stitchを用いて全てのクライアントサイドCoffeeScriptを提供します。