[Grunt][CoffeeScript]ファイルを更新したら自動でCoffeeScriptからminifyされたJSを生成する

目的

ソースファイルを常に監視していて、
更新されたらすぐにテストを流してコンパイル・ミニファイをするような仕組みを作る。
gruntを使用するとこれが実現できる。

インストール

必要なものをインストールする。
これはpackage.jsonで、npm installでインストールさせることにする。
gruntから下が必要なもの。
{
  "name": "sample",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "mocha": "1.14.0",
    "chai":  "*",
    "coffee-script": "1.6.3",
    "sinon": "1.7.3",
    "grunt": "0.4.2",
    "grunt-cli": "0.1.11",
    "grunt-contrib-watch": "0.5.3",
    "grunt-coffeelint": "0.0.7",
    "grunt-contrib-coffee": "0.7.0",
    "grunt-simple-mocha": "0.4.0",
    "grunt-contrib-uglify": "0.2.7"
  }
}

Gruntfile.coffee

Gruntの設定ファイルは以下のようにする。
module.exports = (grunt) ->

  grunt.initConfig
    pkg: grunt.file.readJSON 'package.json'

    coffeelint:
      app:
        files:
          src: [
            'models/*.coffee'
            'specs/*.coffee'
          ]

    simplemocha:
      all:
        src: ['specs/*.coffee']
      options:
        reporter: 'nyan'
        ui: 'bdd'

    coffee:
      compile:
        files: [
          'libs/something.js': 'models/something.coffee',
          'libs/something2.js': 'models/something2.coffee'
        ]
      options:
        bare: yes

    uglify:
      compress_target:
        options:
          sourceMap: (fileName) ->
            fileName.replace /\.js$/, '.js.map'
        files: [
          expand: true,
          cwd: 'libs/',
          src: ['*.js'],
          dest: 'libs/',
          ext: '.min.js'
        ]
 watch:
      scripts:
        files: [
          'models/*.coffee'
          'specs/*.coffee'
        ]
        tasks: [
          #'coffeelint'
          'coffee'
          'simplemocha'
          'uglify'
        ]
        options:
          interrupt: yes

  grunt.loadNpmTasks 'grunt-coffeelint'
  grunt.loadNpmTasks 'grunt-simple-mocha'
  grunt.loadNpmTasks 'grunt-contrib-coffee'
  grunt.loadNpmTasks 'grunt-contrib-watch'
  grunt.loadNpmTasks 'grunt-contrib-uglify'

  grunt.registerTask 'default', [
    #'coffeelint'
    'coffee'
    'simplemocha'
    'uglify'
  ]

watch

以下のwatchの部分が常にファイルを監視する部分。
watch:
      scripts:
        files: [
          'models/*.coffee'
          'specs/*.coffee'
        ]
        tasks: [
          #'coffeelint'
          'coffee'
          'simplemocha'
          'uglify'
        ]
        options:
          interrupt: yes

filesのところが監視するファイル。
tasksのところはファイルの更新があったら実行するタスク。

coffee

以下のcoffeeのところがcoffee scriptをコンパイルする部分。
coffee:
      compile:
        files: [
          'libs/something.js': 'models/something.coffee',
          'libs/something2.js': 'models/something2.coffee'
        ]
      options:
        bare: yes

filesの”:”の左側がコンパイル結果の出力ファイルで右側がコンパイル対象のファイル。

simplemocha

以下がテストの部分。
src:の部分でmochaのテストファイルを指定する。
    simplemocha:
      all:
        src: ['specs/*.coffee']
      options:
        reporter: 'nyan'
        ui: 'bdd'

uglify

以下がミニファイする部分。
cwdのsrcにあるファイルをdest以下に出力する。その際の拡張子はextのようにする。
    uglify:
      compress_target:
        options:
          sourceMap: (fileName) ->
            fileName.replace /\.js$/, '.js.map'
        files: [
          expand: true,
          cwd: 'libs/',
          src: ['*.js'],
          dest: 'libs/',
          ext: '.min.js'
        ]

実行結果

ファイルを更新すると以下のような感じになる。
Waiting...
OK
>> File "specs/something1.coffee" changed.

Running "coffee:compile" (coffee) task
File libs/something1.js created.
File libs/something2.js created.

Running "simplemocha:all" (simplemocha) task
 5   -_-_-__,------,
 0   -_-_-__|  /\_/\
 0   -_-_-_~|_( ^ .^)
     -_-_-_ ""  ""

  5 passing (66ms)

Running "uglify:compress_target" (uglify) task
Source Map "libs/something2.min.js.map" created.
File "libs/something1.min.js" created.
Source Map "libs/something1.min.js.map" created.
File "libs/something1.min.js" created.

Done, without errors.
Completed in 2.046s at Sun Nov 24 2013 18:14:35 GMT+0900 (JST) - Waiting...
  【送料無料】 CoffeeScriptファーストガイド モダンJavaScriptによるアプリケーション開発 / 飯塚直 【単行本】
価格:2,940円(税込、送料込)
zuqqhi2

某Web系の会社でエンジニアをやっています。 学術的なことに非常に興味があります。 趣味は楽器演奏、ジョギング、読書、料理などなど手広くやっています。