HexoでGruntを使ってみました


# はじめに

こんにちは。インフラエンジニアレベル１の[f_prg](http://twitter.com/f_prg "f_prg")です。
HexoでGruntを組み合わせましたので、その構築方法をご紹介します。

# HexoとGruntを組み合わせる
## Gruntとは

[http://gruntjs.com](http://gruntjs.com "http://gruntjs.com")
JavascriptやCSSの縮小、コンパイル、単体テスト、Lintによる厳密なチェックなどを実装できます。
Gurntのタスク起動により自動ビルド化ができるので、WEB開発業務が更に改善できるようです。

![キャプチャ](http://blog.star-flare.com/2014/08/23/hexo_grunt_use/001.png "キャプチャ")

## grunt-cliのインストール
grunt-cliのnpmのパッケージのインストールをします。

```bash
[11:59:18][f_prg@mba:~]# npm install -g grunt-cli
npm http GET https://registry.npmjs.org/grunt-cli
npm http 304 https://registry.npmjs.org/grunt-cli
npm http GET https://registry.npmjs.org/nopt
npm http GET https://registry.npmjs.org/findup-sync
npm http GET https://registry.npmjs.org/resolve
npm http 304 https://registry.npmjs.org/nopt
npm http 304 https://registry.npmjs.org/findup-sync
npm http 304 https://registry.npmjs.org/resolve
npm http GET https://registry.npmjs.org/abbrev
npm http GET https://registry.npmjs.org/glob
npm http GET https://registry.npmjs.org/lodash
npm http 304 https://registry.npmjs.org/abbrev
npm http 304 https://registry.npmjs.org/glob
npm http 304 https://registry.npmjs.org/lodash
npm http GET https://registry.npmjs.org/inherits
npm http GET https://registry.npmjs.org/minimatch
npm http 304 https://registry.npmjs.org/inherits
npm http 304 https://registry.npmjs.org/minimatch
npm http GET https://registry.npmjs.org/lru-cache
npm http GET https://registry.npmjs.org/sigmund
npm http 304 https://registry.npmjs.org/lru-cache
npm http 304 https://registry.npmjs.org/sigmund
/Users/f_prg/.nvm/v0.11.13/bin/grunt -> /Users/f_prg/.nvm/v0.11.13/lib/node_modules/grunt-cli/bin/grunt
grunt-cli@0.1.13 /Users/f_prg/.nvm/v0.11.13/lib/node_modules/grunt-cli
├── resolve@0.3.1
├── nopt@1.0.10 (abbrev@1.0.5)
└── findup-sync@0.1.3 (glob@3.2.11, lodash@2.4.1)
```

## package.jsonにGruntを追加する

下記コマンドで、nodeのpackage.jsonにGruntを追加します。

```bash
[15:28:13][f_prg@mba:blog]# npm install grunt --save
```

package.jsonを確認してみました。

```package.json
  "dependencies": {
    "grunt": "^0.4.5",
```

オプションの--save指定で追加になります。

## grunt-aws-s3プラグインを追加する

同じように、gurnt-aws-s3プラグインを追加します。

```bash
[15:28:56][f_prg@mba:blog]# npm install grunt-aws-s3 --save
npm http GET https://registry.npmjs.org/grunt-aws-s3
npm http 304 https://registry.npmjs.org/grunt-aws-s3
npm http GET https://registry.npmjs.org/mime
npm http GET https://registry.npmjs.org/lodash
npm http GET https://registry.npmjs.org/aws-sdk
npm http GET https://registry.npmjs.org/async
npm http GET https://registry.npmjs.org/setimmediate
npm http 304 https://registry.npmjs.org/mime
npm http 304 https://registry.npmjs.org/lodash
npm http 304 https://registry.npmjs.org/setimmediate
npm http 304 https://registry.npmjs.org/async
npm http 304 https://registry.npmjs.org/aws-sdk
npm http GET https://registry.npmjs.org/aws-sdk-apis
npm http GET https://registry.npmjs.org/xml2js
npm http GET https://registry.npmjs.org/xmlbuilder
npm http 304 https://registry.npmjs.org/xmlbuilder
npm http 304 https://registry.npmjs.org/aws-sdk-apis
npm http 304 https://registry.npmjs.org/xml2js
npm http GET https://registry.npmjs.org/sax
npm http 304 https://registry.npmjs.org/sax
grunt-aws-s3@0.9.1 node_modules/grunt-aws-s3
├── setimmediate@1.0.2
├── mime@1.2.11
├── async@0.2.10
├── lodash@2.4.1
└── aws-sdk@2.0.15 (xmlbuilder@0.4.2, xml2js@0.2.6, aws-sdk-apis@3.1.6)
```

## gruntのセットアップをします

### awsのcredentialのjsonファイルを作成します
AWSのキーとシークレットを外部のjsonファイルで管理します

```aws-credentials.json
{
    "AWSAccessKeyId": "XXXXXXXXXXXXXXXXXXXX",
    "AWSSecretKey": "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
    "AWSRegion": "ap-northeast-1"
}
```

### Grunt.jsファイルでGruntの設定をします

[http://gruntjs.com/api/grunt.option](http://gruntjs.com/api/grunt.option "http://gruntjs.com/api/grunt.option")
[https://www.npmjs.org/package/grunt-aws-s3](https://www.npmjs.org/package/grunt-aws-s3 "https://www.npmjs.org/package/grunt-aws-s3")
を組み合わせてみました。

```Grunt.js
module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    // AWS
    aws: grunt.file.readJSON('aws-credentials.json'),
    aws_s3: {
      options: {
        accessKeyId: '<%= aws.AWSAccessKeyId %>', // Use the variables
        secretAccessKey: '<%= aws.AWSSecretKey %>', // You can also use env variables
        region: '<%= aws.AWSRegion %>',
        uploadConcurrency: 5, // 5 simultaneous uploads
        downloadConcurrency: 5 // 5 simultaneous downloads
      },
      development: {
        options: {
          bucket: 'blog.star-flare.com',
        },
        files: [
          {expand: true, cwd: 'public/', src: '**', dest: 'dev'},
        ]
      },
      staging: {
        options: {
          bucket: 'blog.star-flare.com',
        },
        files: [
          {expand: true, cwd: 'public/', src: '**', dest: 'stg'},
        ]
      },
      production: {
        options: {
          bucket: 'blog.star-flare.com',
          differential: true // Only uploads the files that have changed
        },
        files: [
          {expand: true, cwd: 'public/', src: '**', dest: ''},
        ]
      },
    }
  });

  // AWS
  grunt.loadNpmTasks('grunt-aws-s3');
  var target = grunt.option('target') || 'development';
  grunt.registerTask('default', 'aws_s3:' + target);
};
```
## 静的サイトを生成して、S3にアップロードします

```bash
[23:18:23][f_prg@mba:blog]# hexo generate
[info] Files loaded in 0.855s
  :
  :
  省略します
  :
  :
[info] 62 files generated in 2.604s
[23:22:15][f_prg@mba:blog]# grunt --target production
Running "aws_s3:production" (aws_s3) task
  :
  :
  省略します
  :
  :
12/86 objects uploaded to bucket blog.star-flare.com/

Done, without errors.
```

これで、ブログがS3にアップロードされるようになりました。

# まとめ
今までは静的サイトを生成してからCyberduckを使ってアップロードしてましたが、更に簡単になりました。
targetオプションを使うことで、本番のサイトにアップロードせず確認もできるようになりました。
productionの本番サイトはオプションのdifferentialにより、
更新したファイルだけアップされるようになりました。
Gruntのプラグインで、jsやcssのminifyも組み合わればもっとよくなるでしょう。

# 補足、おまけ
devとstgは、参考のもので使っておりません。
S3のバケットも用意してもいいですね。

# 参考資料・リンク
[http://gruntjs.com](http://gruntjs.com "http://gruntjs.com")
[https://github.com/gruntjs](https://github.com/gruntjs "https://github.com/gruntjs")
[http://gruntjs.com/getting-started](http://gruntjs.com/getting-started "http://gruntjs.com/getting-started")
[http://gruntjs.com/api/grunt.option](http://gruntjs.com/api/grunt.option "http://gruntjs.com/api/grunt.option")
[https://www.npmjs.org/package/grunt-aws-s3](https://www.npmjs.org/package/grunt-aws-s3 "https://www.npmjs.org/package/grunt-aws-s3")