もろず blog

もろちゃんがITに関しての様々なトピックを解説します

Grunt.js を利用した作業の自動化

f:id:chanmoro999:20140317022615j:plain
皆さんは作業の自動化をどれだけ意識したことがあるでしょうか?

とっても単純な作業であっても、
意外にITの現場ではマンパワーで片付けてしまってる場面も多いと感じています


何となく敷居が高そうに感じる"自動化"

プロジェクト単位で取り入れて作業の効率化と品質の向上!
という話になると考えるのが難しいですが、
個人レベルで日々の仕事に取り入れるくらいならサクッとできちゃいます


ちょっとの手間をかけて自動化を取り入れることができれば

  • 何度でも全く同じ作業を間違いなく行うことができる
  • ケアレスミスによるムダな時間ロスが減る
  • 休憩している間に勝手に仕事をやっておいてくれる
  • タスクの細かい手順を覚えておかなくていい
  • クリエイティブな作業そのものに集中できる

と、いいことだらけな未来が待っています


時間に追われているのであればなおさら、
本来パワーをかけるべき仕事に時間と頭を使いたいですよね

そんなタスクの自動化を、
node.js のモジュール Grunt.js でとても簡単に実現することができます


この記事では、
1.Grunt.js ってなに?
2.GruntCLI のインストール
3.Grunt のインストール
4.タスクを定義してみよう
5.様々なプラグインの紹介
について説明します


1.Grunt.js ってなに?

Grunt.js とはタスクの自動化ツールで、
Web制作やアプリ開発の現場でよく取り入れられています

最近のWebやモバイルの世界では より簡単に、より速く開発するためのフレームワークや
プリプロセッサ系言語がたくさん登場しています

そのほとんどは 簡単な形式、簡単なプログラム言語で処理を書いて 目的としていたファイルへ変換するような仕組みなので、
作成したファイルをコンパイルする という作業が必要になります


こういったプロダクトは一度手を出すとやめられないくらい便利なんですが、
複数のものを組み合わせて使う場合に手作業でコンパイルやファイルの移動を行っていると相当に面倒です

そんなルーチンワークを自動化するために Grunt.js が利用されています


利用される具体例としては、
Web制作であれば

アプリ開発であれば

  • リポジトリから最新のソースをチェックアウト
  • ソースの構文チェック
  • アプリをビルド
  • テストコードを実行
  • テスト結果をレポートに出力

なんていうタスクの自動化に Grunt.js が利用されています


単純に逐次実行するだけだったらシェルに書いて終わり って感じなんじですが、
Grunt.js を使うことでイベント駆動による制御やエラー発生時のフローなど、
より細かいタスクフローの設定を行うことが可能です

Java でいう ant と同じようなものらしいです
ant はちゃんと使ったことが無いので説明できないんですが。。。

※Grunt.js 公式サイト
Grunt: The JavaScript Task Runner

記事の先頭に戻る

2.GruntCLI のインストール

Grunt のインストールには

  • GruntCLI
  • Grunt

のインストールが必要です

GruntCLI は Grunt そのものではなく Grunt の機能を利用するためのツール、
Grunt はタスクランナー機能が入った Grunt 本体のパッケージです


ちょっと話が脱線しますが、
node モジュールのインストール方法は大きく2種類存在します

  • サーバー全体で利用されるグローバルインストール
  • プロジェクト単位で利用されるローカルインストール

今回インストールするモジュールは、
GruntCLI は僕らがコマンドラインで利用するツールなのでグローバル、
Grunt はプロジェクト毎に違うバージョンが利用される可能性があるのでローカル、
という理由でインストールする領域を分けます


このあたりは"正しい"というものはないので、
各々の事情や管理方針によって変わるところですね

個人PCで開発用に利用するだけであれば、
特にセンシティブになるところではないのであまり気にしなくていいです


さて、話を戻して Grunt のインストールを進めましょう

まず npm を利用して GruntCLI をインストールします
-g を付けることでグローバルモジュールとしてインストールされます

$ npm install -g grunt-cli

以下のコマンドでバージョンが表示されれば GruntCLI のインストールが完了です

$ grunt --version
grunt-cli v0.1.11


記事の先頭に戻る

3.Grunt のインストール

Grunt のインストールには package.json ファイルを作成する必要があります

package.json とはパッケージのメタ情報や依存関係が定義されています
make でいう Makefile のようなものです


エディタで作成したものをそのまま置いてもいいですし、
以下のコマンドで対話的に package.json を作成することができます

$ npm init


こんな感じで package.json の内容を設定していきます

公開するモジュールではないので特に細かいところを気にする事はないですし、
もし間違って入力しても後から package.json を直せるので大丈夫です

$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sane defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (test) test
version: (0.0.0) 0.0.1
description: test project
entry point: (index.js) 
test command: 
git repository: 
keywords: 
author: 
license: (ISC) 
About to write to /Users/morozumikazuki/test/package.json:

{
  "name": "test",
  "version": "0.0.1",
  "description": "test project",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}


Is this ok? (yes) yes

※package.json の各項目の説明
https://www.npmjs.org/doc/json.html ※npm 公式サイト
npm package.json 日本語版 取扱説明書


package.json が用意できたら Grunt をインストールします

$ npm install grunt --save-dev


--save-dev のオプションを付けると、
package.json の devDependencies にインストールしたパッケージの情報を追記してくれます

{
  "name": "test",
  "version": "0.0.1",
  "description": "test project",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "grunt": "~0.4.4"
  }
}


最後に Grunt のバージョンを確認します

$ grunt --version
grunt-cli v0.1.11
grunt v0.4.4

これで Grunt のインストールは完了です

記事の先頭に戻る

4.タスクを定義してみよう

Grunt に実行してもらうタスクを Gruntfile.js に記述します

Gruntfile.js はJavaScript で書かれたファイルですが、
雰囲気が理解できればそんなに難しくないです

特に Grunt プラグインを利用する場合は、
JSON 形式で設定を書くだけなのでとても簡単です


ここでは例として、

  • scss ファイル、js ファイルの更新を監視
  • scss ファイルが更新されたら compass でコンパイル
  • js ファイルが更新されたら圧縮

というタスクを定義してみます

f:id:chanmoro999:20140317015527j:plain

このタスクに必要な機能は以下の3つの Grunt プラグインで提供されています

  • grunt-contrib-watch :ファイルの更新を監視する機能
  • grunt-contrib-compass :compass の機能
  • grunt-contrib-uglify :JavaScript の圧縮機能

まずはそれぞれのプラグインを npm でローカルインストールします

$ npm install grunt-contrib-watch --save-dev
$ npm install grunt-contrib-compass --save-dev
$ npm install grunt-contrib-uglify --save-dev


次にタスク内容を Gruntfile.js で定義します
先ほどのタスクを書くとこうなります

module.exports = function (grunt) {
  // Grunt プラグインの呼び出し
  grunt.loadNpmTasks('grunt-contrib-compass');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-uglify');

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    // タスク watch の設定 ※タスクは grunt-contrib-watch で定義
    // 監視対象ファイル、実行するタスク名を指定
    watch: {
      // scssファイル監視
      scripts_css: {
        files: ['**/*.scss'], 
        tasks: ['compass'], 
        options: {
          spawn: false,
        },
      },
      // jsファイル監視
      scripts_js: {
        files: ['**/*.js'],
        tasks: ['uglify'],
        options: {
          spawn: false,
        },
      },
    },
    // タスク compass の設定 ※タスクは grunt-contrib-compass で定義
    // SCSS ファイルの配置場所、CSS ファイルの出力先、圧縮の有無を指定
    compass: {
      dist: {
        options: {
          sassDir: '_sass/',         
          cssDir: 'shared/css/',
          outputStyle: 'compressed',
        }
      }
    },
    // タスク uglify の設定 ※タスクは grunt-contrib-uglify で定義
    // 圧縮対象のファイル、出力先を指定
    uglify: {
      options: {
        mangle: true,
      compress: true,
        beautify: false,
      },
      targets: {
        files: {
          'shared/js/jsfile.min.js': ['shared/js/jsfile.js']
          }
      }
    }
  });

  // Grunt のデフォルトタスク定義
  // 複数タスクを指定することも可能
  grunt.registerTask('default', ['watch']);
};

これを package.json と同じディレクトリに配置します

Gruntfile.js を配置したディレクトリで grunt コマンドを実行すると
定義されたタスクが開始されます

$ grunt
Running "watch" task
Waiting...


grunt コマンドの引数にはタスク名を指定することができ、
引数なしの場合はデフォルトタスクが実行されます

今回はデフォルトタスクに watch タスクを指定したので、
以下の2つはどちらも同じタスクが実行されることになります

$ grunt
$ grunt watch


これで無事タスクを定義することができました


記事の先頭に戻る

5.様々なプラグインの紹介

先ほどのタスク定義でも使っていますが、
様々な定義済み Grunt タスクがプラグインとして公開されていて、
そのほとんどが GitHub でソースコードも公開されています

また、各プラグインで指定できるオプションについても、
それぞれの Github 上のページに解説が載っています

特によく利用されるものは、
grunt-contrib というプレフィクスがついた Grunt 公式プラグインにて提供されています

個別にインストールすることもできますし、
grunt-contrib をインストールすれば全部入りになっています

先ほど利用した watch、compass、uglify も grunt-contrib の一部です

※grunt-contrib の 解説
grunt-contrib - npm


自分がやろうとしていることはたいてい他の誰かが既にトライしてくれているので、
ありがたく先人の知恵を頂いて生かしましょう


ちなみに Grunt プラグインの内部では以下のようなコードで
Grunt へのタスク追加がされています

module.exports = function (grunt) {
    grunt.registerTask('taskName', 'discription.', function() {
            // タスク内容を記述
        }
    });
};

タスクの作成については以下のサイトで詳しく解説されていますので、
参考にしてみてください
タスクの作成 | Grunt 日本語リファレンス | js STUDIO


さて、今回は Grunt を利用したタスクの自動化についてご紹介しました


僕は Grunt を使い始めたのは最近ですが、
ファイルのバックアップやコピーなんかの細かい作業を自動化するだけでもだいぶ効果を実感できます

気にすることを1つでも減らして頭の中の余裕が増やすことは、
僕らの想像以上に大きなメリットをもたらしてくれます


こういった便利なものはどんどん取り入れて、
仕事の質を高めていきたいですね


記事の先頭に戻る