Gruntでbrowserify使ってCoffeescriptをコンパイルする。

なんかCoffeescriptをGruntでコンパイルして、concatしたりとかだるいなーってずーっと思ってました。
Classとかを他のファイルから参照しようとするとwindow.classNameとか@classNameとかにしないといけないですし、ファイル名順に結合するので、アルファベット順で後ろにくるクラスを読もうとするとエラー吐いたり、いまいち依存関係が見えなかったり。

小規模な開発であれば問題ないのですが、Coffeescriptで大量にClassを作ったりすると、結構大きな問題になってきます。かといってrequire.jsとか面倒くさい。

というわけで、最近流行のbrowserifyを使ってみました。

npmとbrowserifyを使ったクライアントサイドのウェブアプリ開発
Browserify: それはrequire()を使うための魔法の杖

ざっくり言うと、ブラウザで、node.jsのようなrequireが使えるようになるツールです。

たとえば、以下のようなHoge.coffeeがあるとすると

class Hoge
    piyo: ->

module.exports = Hoge

以下のコードで、読み込んでくることができるという代物です。

Hoge = require("./Hoge")
hoge = new Hoge()

debowerifyとかをtransformに指定しておくと、bowerでインストールしたモジュールなんかも取ってこれるので、大変素敵です。

$ = require("jquery")

それをgruntでファイル監視して自動化するようにしたのがこちらです。

module.exports = function(grunt) {
  grunt.initConfig({
    dir: {
      coffee: 'coffee',
      javascripts: 'javascripts'
    },
    esteWatch: {
      options: {
        dirs: [ 'coffee/**' ],
        extensions: ['coffee'],
      }
      coffee: function(filepath) {
        return ["browserify"];
      }
    },
    browserify: {
      dist: {
        files: {
          'javascripts/all.js': ['coffee/all.coffee']
        },
        options: {
          transform: ['coffeeify', "debowerify"],
          browserifyOptions: {
            extensions: ['.coffee']
          }
        }
      }
    }
  });
  grunt.loadNpmTasks('grunt-browserify');
  grunt.registerTask('default', ['esteWatch']);
};

transformにcoffeeifyを設定しておくと、CoffeeScriptでもコンパイルできるようになります。
browserifyOptionsのextensionsに.coffeeを指定しておくと、CoffeeScriptのファイルでも拡張子を省略してrequireできました。

名前空間も汚染しないし、依存するClass等は明示的になるし、読み込み順に左右されないJSを書くことができるようになります。その代わり、$ = require(“jquery”)等は各ファイルで行う必要があります。実行時には一度しか読み込まれないようなので、パフォーマンス的にもよろしいです。

GruntでBowerしたり、Coffeeしたり、ConcatしてJSを書いている人にはホントに便利です。