jade, sass/compass, coffeescript, bowerで静的Webサイトを作るGrunt.js秘伝のタレ

最近のフロントエンド開発、静的サイト開発

- HTMLを書くのに[Jade](http://jade-lang.com/)を使いたい
- CSSを書くのにsass/[compass](http://compass-style.org/)を使いたい
- Javascriptを書くのに[Coffeescript](http://coffeescript.org/)を使いたい
- Javascriptのライブラリ管理に[Bower](http://bower.io/)を使いたい
- コンパイル処理の自動化などは[Grunt.js](http://gruntjs.com/)を使いたい

sass/compassをつかうためにはrubyのcompass gemをインストールしないといけないのでnodeだけで完結できないのがネック。
とはいえ一番つかわれていそうなのがsassで、Stylusは日本語ドキュメントが少なかったり利用事例が少ないのでまだ早い感がある。

# ディレクトリ構成
```
.
├── jade              Jade置き場所
│   └── index.jade
├── sass              sass置き場所
│   └── index.sass
├── coffee            Coffeescript置き場所
│   └── index.coffee
├── .bowerrc          bowerでJavascriptライブラリをどこにインストールするかの設定
├── bower.json        bowerでインストールしたいJavascriptライブラリ一覧
├── bower_components  bowerのJavascriptライブラリインストール先
├── gruntfile.coffee  grunt設定ファイル
├── package.json      gruntで使うnpmパッケージ一覧
├── node_modules      npm パッケージインストール先
└── public            コンパイル先
```


# bower
`npm install bower -g` でインストール

## .bowerrc
プロジェクトディレクトリのルートに `.bowerrc` という名前のファイルをつくる。

```json
{
    "directory": "bower_components"
}
```

## bower.json
プロジェクトディレクトリのルートで
`bower init` で `bower.json` が生成される。
`bower install hoge -save` することでパッケージ情報が `bower.json` に保存されていく。

実際はインストールされたcomponentのなかから必要なjsファイルをpublicディレクトリへコピーなどをして使う必要があるが、それはgruntで自動化する。

この手順を踏まないでbowerのインストール先をいきなりpublicディレクトリにすると不要なファイルまで公開することになるのであまりオススメできない。

# grunt
## gruntでやりたいこと
- `/jade` にある Jadeファイルをコンパイルして `/public` に配置
- `/sass` にある sassをコンパイルして `/public/css` に配置
- `/coffee` にある coffeescriptをコンパイルして `/public/js` に配置
- ファイルが変更されたら、変更されたファイルだけを対象に、自動でコンパイルを実行する
- インストール済みbower componentsのmain jsファイルを `/public/lib` フォルダに配置
- ポート3000でHTTPサーバーを立ち上げてブラウザでチェックできるようにする
    - コンパイルが完了するたびに自動でブラウザをリロードする

## gruntfile.coffee

```coffeescript:gruntfile.coffee
module.exports = (grunt) =>
    grunt.initConfig
        pkg: grunt.file.readJSON('package.json')
        jade:
            compile:
                options:
                    pretty: true
                files: [
                    expand: true
                    cwd: 'jade'
                    src: ['*.jade']
                    dest: 'public/'
                    ext: '.html'
                ]
        compass:
            dist:
                options:
                    sassDir: "sass"
                    cssDir: "public/css/"
        coffee:
            compile:
                options:
                    bare: true
                files: [
                    expand: true
                    cwd: 'coffee'
                    src: ['**/*.coffee']
                    dest: 'public/js/'
                    ext: '.js'
                ]
        bower:
            install:
                options:
                    targetDir: 'public/lib'
                    layout: 'byType'
                    install: true
                    cleanTargetDir: true
                    cleanBowerDir: false
        connect:
            server:
                options:
                    port: 3000
                    hostname: "*"
                    base: 'public'
                    livereload: 35729
        esteWatch:
            options:
                dirs: [
                    "coffee/**"
                    "jade/**"
                    "sass/**"
                    "public/**"
                ]
                livereload:
                    enabled: true
                    extensions: ['js', 'html', 'css']
                    port: 35729
            "coffee": (path) ->
                ['newer:coffee']
            "jade": (path) ->
                ['newer:jade']
            "sass": (path) ->
                ['newer:compass']
    grunt.loadNpmTasks 'grunt-contrib-jade'
    grunt.loadNpmTasks 'grunt-contrib-compass'
    grunt.loadNpmTasks 'grunt-contrib-coffee'
    grunt.loadNpmTasks 'grunt-bower-task'
    grunt.loadNpmTasks 'grunt-contrib-connect'
    grunt.loadNpmTasks 'grunt-este-watch'
    grunt.loadNpmTasks 'grunt-newer'
    grunt.registerTask 'make', ['bower', 'newer:coffee', 'newer:jade', 'newer:compass']
    grunt.registerTask 'default', ['make', 'connect', 'esteWatch']

```

特筆すべき便利情報としては、
- `grunt-bower-task` つかうとbower componentのmain jsファイルから必要なファイルだけ配置できていいですよ
- `grunt-contrib-connect` っていうの使うとサーバー立ち上がってファイル更新されたら自動リロードとかできていいですよ
- `grunt-este-watch` のほうがgrunt-contrib-watchよりも軽いしいいですよ
- `grunt-newer` っていうのを使うと魔術的なことが起きて各タスク名のまえに `newer:` ってつけるだけで更新されたファイルだけを対象にタスクが実行されていいですよ

といったあたりでしょうか。

大規模なJavascriptやSingle-page applicationを開発する場合は上記に加えてテストランナーの役割もgruntにやらせてるんだけど、とりあえず静的サイト作る場合をノウハウとしてアウトプットしておきたかったので今回はここまで。