The Little Book on CoffeeScript

自動的にCoffeeScriptをコンパイルする

CoffeeScriptの問題はあなたとJavaScriptの間に他のレイヤーを増やすことです。CoffeeScriptのファイルが変更され、古くなる度に手動でコンパイルせねばなりません。幸いなことにCoffeeScriptはいくつかのコンパイル代替形態を持っており、開発サイクルをいくらかスムーズにすることが可能です。

最初の章で説明したとおり、CoffeeScriptはcoffeeコマンドを用いてコンパイル可能です。

coffee --compile --output lib src

上の例では全てのsrcディレクトリ内の.coffeeファイルはコンパイルされ、libディレクトリに個々の出力が置かれます。これを呼ぶだけでもちょっと面倒かもしれません。自動化する方法を探しましょう。

Cake

CakeはとてもシンプルなビルドシステムでMakeRakeに倣っています。このライブラリはcoffee-scriptのnpmパッケージにバンドルされておりcakeという名前のコマンドで利用可能です。

Cakefileと呼ばれるファイルにCoffeeScriptを用いることでタスクを定義できます。cake [task] [options]を同じディレクトリで実行することにより、Cakeがそれらのタスクを取り上げ、起動します。全てのタスクとオプションのリストを表示するにはただcakeと入力します。

タスクはtask()関数を用いて定義します。名前と任意で詳細説明とコールバック関数を与えます。例としてCakefileという名のファイルを作り、libsrcという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のコンパイルをリクエスト/レスポンスサイクルに統合せねばなりません。色々な統合ソリューションが人気の高いバックエンドの言語とフレームワークに対して既に存在します。例えばRailsDjangoです。

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を提供します。