Grunt導入してみた

MacにはCodeKitっていうCoffeeScriptとかSassとかLessとかをコンパイルしてくれる便利なツールがあって最近までお世話になってた。でも自分はWindowsユーザーで、これだけのためにMacを起動するのも面倒くさいので、CodeKitでやってたことをWindowsでもできるようにとGruntをはじめてみた。

Gruntそのものはコンパイラではなく、いろんなタスクを実行してくれるだけのツールなんだけど、プラグインを追加することでCoffeeScriptのコンパイルや、Sass/Lessのコンパイル、Uglifyを使ってjsのminifyなどができるようになる。

これを使ってCodeKitでやってたことを再現してみた。

1. インストール

まずGruntを実行するのに必要なnode.jsをインストール。同時にnpm(node.js用のパッケージ管理ツール)もインストールされる。

環境変数PATHに「C:\Users\{ユーザー名}\AppData\Roaming\npm;C:\Program Files\nodejs\」を追加しておく。

gruntをインストール

npm install -g grunt-cli

※「npm install -g grunt」ではない

環境変数PATHに「grunt」を追加しておく。

参考:
Windows 環境変数 Path の設定方法 – コンピュータ/ソフトウェア関連Tips
はじめに | Grunt 日本語リファレンス | js STUDIO

2. プロジェクトの準備

プロジェクトのルートフォルダにGruntfile.js(もしくはGruntfile.coffee)と、package.jsonというファイルを作る。
Gruntfile.js(Gruntfile.coffee)はGruntに実行させるタスクを定義しておくファイル。package.jsonはプロジェクトに必要なGruntのプラグインのリスト。

3. package.json

package.jsonはこのように記述して、devDependenciesに必要なプラグイン(パッケージ)の名前とバージョンを羅列しておく。

{
  "name": "{プロジェクト名}",
  "version": "{パッケージのバージョン}",
  "author": "{作者}",
  "devDependencies": {
    "grunt": "~0.4.1",
    "grunt-contrib-livereload": ">=0.0.0",
    "grunt-contrib-watch": ">=0.0.0",
    "grunt-contrib-coffee": ">=0.0.0",
    "grunt-contrib-uglify": ">=0.0.0",
    "grunt-contrib-jshint": ">=0.0.0",
    "grunt-contrib-jst": ">=0.0.0",
    "grunt-contrib-sass": ">=0.0.0",
    "grunt-contrib-compass": ">=0.0.0",
    "grunt-contrib-cssmin": ">=0.0.0"
  }
}

package.jsonを用意した状態で「npm install」をコマンドプロンプト上で実行すると、devDependenciesに書かれたプラグインを順番にプロジェクトフォルダ直下のnode_modulesフォルダにダウンロードしてきてくれる。

npm install

と書かれた.batファイルを作っておくと良い。

参考:
npm-json(1) — Specifics of npm’s package.json handling
npm と package.json でパッケージ管理 | FIRN.JP
npmとpackage.json使い方 – Kokudoriing

4. Gruntfile.js

下記のようなラッパー関数を用意し、その中にタスクを書いていく。Gruntfile.jsの内容はGruntを通してnode.js上で実行されるので、js(もしくはCoffee Script)で記述していく。

module.exports = function(grunt)
{
  //ここにGruntに実行させたいタスクを書いていく
};

coffeeファイルが入ったフォルダを監視してcoffeeファイルが更新されたらCoffeeScriptをコンパイルして、uglifyでminifyするGruntfile.coffee。

module.exports = (grunt) ->

    # load tasks
    grunt.loadNpmTasks "grunt-contrib-coffee"
    grunt.loadNpmTasks "grunt-contrib-uglify"
    grunt.loadNpmTasks "grunt-contrib-watch"

    grunt.initConfig(

        coffee:
            files:
                expand: true
                cwd: "assets/coffee/"
                src: ["**/**/*.coffee"]
                dest: "assets/js/"
                ext: ".js"

        uglify:
            files:
                expand: true
                cwd: "assets/js/"
                src: ["*.js"]
                dest: "assets/js/"
                ext: ".min.js"
            options: ""

        watch:
            coffee:
                files: ["assets/coffee/**/*.coffee"]
                tasks: [
                    "coffee"
                    "uglify"
                ]
	)

    grunt.registerTask "default", ["watch"]

sassファイルが入ったフォルダを監視してsassファイルが更新されたらSassをコンパイルして、sprite画像も生成する。

module.exports = (grunt) ->

    # load tasks
    grunt.loadNpmTasks "grunt-contrib-compass"
    grunt.loadNpmTasks "grunt-contrib-cssmin"
    grunt.loadNpmTasks "grunt-contrib-watch"

    grunt.initConfig(

        compass:
            dist:
                options:
                    environment: "development"
                    outputStyle: "compressed"
                    debugInfo: true
                    relativeAssets: true
                    basePath: "assets"
                    sassDir: "sass"
                    cssDir: "css"
                    generatedImagesDir: "images"

        cssmin:
            files:
                expand: true
                cwd: "assets/css"
                src: ["*.css", "!*.min.css"]
                dest: "assets/css/"
                ext: ".min.css"

        watch:
            sass:
                files: ["assets/sass/**/*.sass"]
                tasks: [
                    "compass"
                    "cssmin"
                ]
	)

    grunt.registerTask "default", ["watch"]

これらをまとめつつ、JavaScriptテンプレートのコンパイル、htmlの更新監視にコンパイル後にLiveReloadを使ってブラウザをリロードするタスクを加えるとこうなる。

module.exports = (grunt) ->

    # load tasks
    grunt.loadNpmTasks "grunt-contrib-compass"
    grunt.loadNpmTasks "grunt-contrib-cssmin"
    grunt.loadNpmTasks "grunt-contrib-coffee"
    grunt.loadNpmTasks "grunt-contrib-uglify"
    grunt.loadNpmTasks "grunt-contrib-jst"
    grunt.loadNpmTasks "grunt-contrib-watch"

    grunt.initConfig(
        compass:
            dist:
                options:
                    environment: "development"
                    outputStyle: "compressed"
                    debugInfo: true
                    relativeAssets: true
                    basePath: "assets"
                    sassDir: "sass"
                    cssDir: "css"
                    generatedImagesDir: "images"
        cssmin:
            files:
                expand: true
                cwd: "assets/css"
                src: ["*.css", "!*.min.css"]
                dest: "assets/css/"
                ext: ".min.css"
        coffee:
            files:
                expand: true
                cwd: "assets/coffee/"
                src: ["**/**/*.coffee"]
                dest: "assets/js/"
                ext: ".js"
            options:
                sourceMap: true
        jst:
            compile:
                options:
                    processName: (filename) ->
                        return filename.match(/assets\/jst\/(.*).js$/)[1]
                files:
                    "assets/js/templates.js": ["assets/jst/**/**/*.js"]
        uglify:
            files:
                expand: true
                cwd: "assets/js/"
                src: ["*.js"]
                dest: "assets/js/"
                ext: ".min.js"
            options: ""
        watch:
            html:
                files: ["**/*.html"]
                options:
                    livereload: true
            coffee:
                files: ["assets/coffee/**/*.coffee"]
                tasks: [
                    "start"
                    "coffee"
                    "uglify"
                ]
                options:
                    livereload: true
            jst:
                files: ["assets/jst/**/*.js"]
                tasks: [
                    "jst"
                    "uglify"
                ]
                options:
                    livereload: true
            sass:
                files: ["assets/sass/**/*.sass"]
                tasks: [
                    "start"
                    "compass"
                    "cssmin"
                ]
                options:
                    livereload: true
    )

    # register tasks
    grunt.registerTask "start", "start task", ->
        grunt.log.writeln "--------------------------------------------------------"
        grunt.log.writeln "    start task"
        grunt.log.writeln "--------------------------------------------------------"

    grunt.registerTask "default", ["watch"]

それぞれのタスクの設定はそれぞれのプラグインのページを参照のこと。

参考:
grunt-contrib-coffee
grunt-contrib-jst
grunt-contrib-uglify
grunt-contrib-compass
grunt-contrib-cssmin
grunt-contrib-watch