Gruntを使っていろいろ自動化するためのメモ

駆け出しフロントエンジニアの実に個人的なメモ。
※順次更新予定

# Gruntを使って自動化しよう
[Grunt: The JavaScript Task Runner](http://gruntjs.com/)
Gruntとは自動化することと見つけたり。

## やりたいこと
* HTML書くからHTML Validator
* CSS書くからCompass、Autoprefixer
* JavaScript書くからJSHint、テストするやつ
* ドキュメント作成するやつ（CSS/JavaScript）
* ファイル更新したら自動でタスク実行してくれるやつ
* その他、便利になるやつ

## やったこと

### 1. Gruntのインストール
#### 1. Node.jsのインストール
Homebrewでインストールしてたけど、nvmに切り替えてた。
参考：[【Node.js】nvmをインストールして設定するまでの方法](http://creator.cotapon.org/articles/node-js/%E3%80%90node-js%E3%80%91nvm%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%97%E3%81%A6%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B%E3%81%BE%E3%81%A7%E3%81%AE%E6%96%B9%E6%B3%95)

#### 2. grunt-cliのインストール
`$ npm install -g grunt-cli`
-gオプションでどこでも使えるようにインストールしてる。

#### 3. package.jsonの作成
` $ mkdir proj_dir && cd $_
$ npm init`
npmでインストールしたパッケージを管理するJSONファイルを作成する。

#### 4. Grunt本体のインストール
`$ npm install grunt --save-dev`
--save-devオプションでpackage.jsonに依存性を記録するんだとか。
違う環境でもpackage.jsonを使いまわすとバージョン指定でインストールが可能。
-gオプションなしなので、gruntはここでしか使えない。

#### 5. Gruntfileの作成
タスクを記述するGruntfileをとりあえず空の状態で作成。

```js:Gruntfile.js
module.exports = function(grunt){
  grunt.initConfig({});
  grunt.registerTask('default',[]);
};
```

### 2. Compassプラグインの導入
####1. [grunt-contrib-compass](https://www.npmjs.org/package/grunt-contrib-compass)のインストール
`$ npm install grunt-contrib-compass --save-dev`

#### 2. Gruntfileの編集
Compassタスクの設定を追加する。
Compassはインストール済み。とりあえず、config.rbファイルを指定するだけ。

```js:Gruntfile.js

    compass: {
      dist: {
        options: {
          config: 'config.rb'
        }
      }
    }

  grunt.loadNpmTasks('grunt-contrib-compass');
  grunt.registerTask('default',['compass']);
```

#### 3. compassタスクの実行
defaultに登録してあるので、gruntコマンドだけで実行される。

```zsh:
$ grunt
Running "compass:dist" (compass) task
（中略）
Done, without errors.
```

### 3. JSHintプラグインの導入
#### 1. [grunt-contrib-jshint](https://www.npmjs.org/package/grunt-contrib-jshint)のインストール
`$ npm install grunt-contrib-jshint --save-dev`

#### 2. Gruntfileの編集
.jshintrcファイルを用意して、オプション指定はそこに記述。
管理の都合上、jshintrc.jsonにリネーム。

```js:Gruntfile.js
    jshint: {
      files: ['js/*.js'],
      options: {
        jshintrc: 'jshintrc.json',
        force: true
      }
    }

  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.registerTask('default',['compass','jshint']);
```


#### 3. jshintタスクの実行
ここでもとりあえずdefaultに登録したので、gruntコマンド。

```zsh:
$ grunt
（中略）
Running "jshint:files" (jshint) task
>> 1 file lint free.

Done, without errors.
```

#### 注意事項
タスク追加していくうえで
`grunt.registerTask('jshint',['jshint']);`
のように同じ名前でタスク登録するとエラーが出るので注意する。

```zsh:エラー内容
util.js:35
  var str = String(f).replace(formatRegExp, function(x) {
                      ^
```

また、JSHintで引っかかった時に以下のような警告が出る。
エラーが出るとタスクがそこで止まるので、処理を続けたい場合はforceオプションを追加。
`Warning: Task "jshint:files" failed. Use --force to continue.`

### 4. Watchプラグインの導入
`$ compass watch`
みたいに、ファイルの更新を監視して自動でタスクを実行したらコマンド打つ手間が省けるので、そのためのWatchプラグイン。
まずはCompassとJSHintのタスクを自動で実行させる。

#### 1. [grunt-contrib-watch](https://www.npmjs.org/package/grunt-contrib-watch)のインストール
`npm install grunt-contrib-watch --save-dev`

#### 2. Gruntfileの編集

```js:Gruntfile.js
    watch: {
      scripts: {
        files: ['scss/*.scss','js/*.js'],
        tasks: ['compass','jshint']
      }
    }

  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.registerTask('start',['watch']);
```

#### 3. watchタスクの実行

```zsh:
$ grunt start
Running "watch" task
Waiting...
```

### 5. html-validationプラグインの導入
#### 1. [grunt-html-validation](https://www.npmjs.org/package/grunt-html-validation)のインストール
`npm install grunt-html-validation --save-dev`

#### 2. Gruntfileの編集

```js:Gruntfile.js
    validation: {
      files: ['*.html'],
      options: {
        reset: true,
        doctype: 'HTML5',
        charset: 'utf-8',
        stoponerror: false
      }
    }

  grunt.loadNpmTasks('grunt-html-validation');
  grunt.registerTask('html',['validation']);
```

#### 3. validationタスクの実行

```zsh:
$ grunt html
Running "validation:files" (validation) task
Validation started for.. index.html
>> Validation successful..
Validation report generated: validation-report.json

Done, without errors.
```

やったね！今日はここまで！ :smile: 

## 現在までのGruntfile.js

```js:Gruntfile.js
module.exports = function(grunt){
  grunt.initConfig({
    validation: {
      files: ['*.html'],
      options: {
        reset: true,
        doctype: 'HTML5',
        charset: 'utf-8',
        stoponerror: false
      }
    },
    compass: {
      dist: {
        options: {
          config: 'config_dev.rb'
        }
      }
    },
    jshint: {
      files: ['js/*.js'],
      options: {
        jshintrc: 'jshintrc.json',
        force: true
      }
    },
    watch: {
      html: {
        files: ['*.html'],
        tasks: ['validation'],
        options: ['changed','added','deleted'] // = all
      },
      css: {
        files: ['scss/*.scss'],
        tasks: ['compass'],
        options: ['changed','added','deleted'] // = all
      },
      javascript: {
        files: ['js/*.js'],
        tasks: ['jshint'],
        options: ['changed','added','deleted'] // = all
      }
    }
  });
  grunt.loadNpmTasks('grunt-html-validation');
  grunt.loadNpmTasks('grunt-contrib-compass');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.registerTask('start',['watch']);
  grunt.registerTask('default',['validation','compass','jshint']);
};
```

## 参考にした書籍
![フロントエンドエンジニア養成読本](http://ecx.images-amazon.com/images/I/51XYWUokftL._SL200_.jpg)
[フロントエンドエンジニア養成読本](http://www.amazon.co.jp/dp/4774165786/)