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

CoffeeScript付属の軽量ビルドツールcakeを使ってみる

CoffeeScript

CoffeeScriptにCakeというビルドツールが付属している。

RubyでいうところのRakeみたいなものだが、Rakeよりは機能が小さい。Rubyを使いこなせる人はRakeを使えばいいと思う。

makeでMakefileを、rakeでRakefileを用意してその中にtaskを記述するように、cakeでもCakefileというのを用意する。

$ tree
.
|-- Cakefile
`-- src
    |-- coffee
    |   |-- intro.coffee
    |   |-- main.coffee
    |   `-- outro.coffee
    `-- js

3 directories, 4 files

ここではintro.coffee、main.coffee、outro.coffeeをくっつけて一つのCoffeeScriptとしてsrc/js/main.jsにコンパイルするタスクは次のようになる。

fs     = require 'fs'
{exec} = require 'child_process'
util   = require 'util'

srcCoffeeDir = 'src/coffee'

targetJsDir = 'src/js'

targetFileName = 'main'
targetCoffeeFile = "#{srcCoffeeDir}/#{targetFileName}.coffee"
targetJsFile = "#{targetJsDir}/#{targetFileName}.js"

coffeeOpts = "--output #{targetJsFile} --compile #{targetCoffeeFile}"

coffeeFiles = [
  'intro'
  'main'
  'outro'
]

task 'build', 'Build single JavaScript file from source files', ->
  util.log "Building #{targetJsFile}"
  appContents = new Array remaining = coffeeFiles.length
  util.log "Appending #{coffeeFiles.length} files to #{targetCoffeeFile}"

  for file, index in coffeeFiles then do (file, index) ->
    fs.readFile "#{srcCoffeeDir}/#{file}.coffee"
              , 'utf8'
              , (err, fileContents) ->
      util.log err if err

      appContents[index] = fileContents
      util.log "[#{index + 1}] #{file}.coffee"
      process() if --remaining is 0  # (***)

  process = ->
    fs.writeFile targetCoffeeFile
               , appContents.join('\n\n')
               , 'utf8'
               , (err) ->
      util.log err if err

      exec "coffee #{coffeeOpts}"
         , (err, stdout, stderr) ->
        util.log err if err
        message = "Compiled #{targetJsFile}"
        util.log message 
        fs.unlink targetCoffeeFile, (err) -> util.log err if err

シェルでcakeとだけ入力すると、登録されているtaskとその詳細が出力される。

$ cake

cake build               # Build single JavaScript file from source files

cake nameでtaskを起動する。

$ cake build
22 Jan 22:42:43 - Building src/js/main.js
22 Jan 22:42:43 - Appending 3 files to src/coffee/main.coffee
22 Jan 22:42:43 - [1] intro.coffee
22 Jan 22:42:43 - [2] main.coffee
22 Jan 22:42:43 - [3] outro.coffee
22 Jan 22:42:43 - Compiled src/js/main.js

一つだけ注意点があって、(***)という部分でわざわざprocess関数をコールバック関数内で実行しているのは、node.jsではIOがノンブロッキングだからです。node.jsのnode.jsたる所以ですね。