Grunt Xmas!!!

いまやさんからバトンタッチ! みなさんこんにちは! すっかりフロントエンド開発では定着したGruntの話はもう飽きてると思いますが、今日はフロントエンドではなく、バックエンドエンジニア向けにどう活用できるかをご紹介したいと思います。

※このエントリは GREE Advent Calendar 2013 9日目の記事です。

自己紹介

石川将行と申します。IDは ishikawam か M_Ishikawa です。ソーシャルゲームの開発エンジニアです。

ぼくのチームではGruntはフロントエンド(HTML, JS, CSS等マークアップ)制作のエンジニアだけでなくバックエンド(PHP等サーバサイド)開発のエンジニアも使ってます。
双方ともに同じリポジトリで同じGruntの設定(=Gruntfile.js)を共有しています。

backend_frontend

Gruntはプロジェクトをビルドするためのスクリプト(タスク)を自由に組み合わせることができるので、担当者の役割(この場合はフロントエンドとバックエンド)によってうまく使い分けることができます。

Gruntのおさらい

grunt-title

今年はPHPCONとかYAPC AsiaとかでGruntの話をさせていただきましたのでそこから抜粋しておさらいします。

Gruntとは、

  • Node.js製のフロントエンド開発支援ツール
  • フロントエンド関連ファイルのビルドを行う
    • オリジナルと公開用とにディレクトリを分けて管理し、公開用には画像を圧縮したりJSを難読化したりCSSプリプロセッサ変換(Sass等)をしたりテストしたり etc... ができます。
  • プラグインによりツールを拡張できる
    • プラグインの開発が簡単(JavaScript)

といった特徴があります。

もっとわかりやすく、例えば何ができるかというと

  • CoffeeScriptを変換する
  • 画像を圧縮したり管理したりする
  • JSを難読化する
  • ファイル名をハッシュで隠蔽する
  • Sassを変換する(Compass)
  • シンタックスチェック(LINTチェック)する
  • CSSを圧縮する
  • ユニットテストを走らせる
  • ファイルやコードの置換or変換スクリプトを実行する
  • etc...

などなど、開発していてコードを書く以外のことをまとめてやってくれます。

Gruntはnpmで管理されており(つまりNode.jsモジュール)、実質各機能(タスク)を担当するGruntプラグインもまたnpmで管理されています。
npmはパッケージ管理だけでなく依存管理、つまりNode.js版のComposer(PHP), Bundler(Ruby), Carton(Perl) のような管理機能をも持ち合わせていると考えていただければよろしいかと思います。

Gruntのライバル?

GruntはNode.jsの流れに乗ってすごい速さで成長しており、v0.4が今年の2月にリリースされた当時はnpmに登録されたプラグインの数は1,000に満たなかったのですが、12/5時点で1,900にも登っています。
そういう意味では枯れてきており、似たようなもので比較的新しいBrunchというツールと比較されることもありますが、これはフロントエンドエンジニアがモックを最速で作るまではいいですが、継続的にプロジェクトで使っていくとなるとプラグインの拡張性の問題(数が比じゃない)、独自プラグインを気軽に扱えること、等を考えればGruntに取って代わるものとはいえません。人気も相まってGruntプラグインはフロントエンド制作の域を大きく超えてきています。

YeomanはGruntとJSライブラリ管理ツールのBowerとを組み合わせたものです。モックを爆速で作りたい場合には非常に有効かつ継続的にも利用できます。(我がチームはYeomanではないですがBowerも導入しています。)

どうやって使ってるか

ぼくのチームではこんな感じで使ってます。

Gruntプラグイン 内容
(grunt) Grunt本体です。npmで管理されているのでGruntもひとつのNode.jsのモジュールとして扱われます。
grunt-contrib-compass SassをCSSのへコンバートするCompassを実行
grunt-contrib-imagemin pngmin, jpegtran等画像圧縮ツールを実行
grunt-contrib-concat ファイルを結合
grunt-contrib-uglify JSを圧縮・難読化
grunt-contrib-cssmin CSSを圧縮
grunt-contrib-copy ファイルのコピー
grunt-contrib-clean ファイルの削除
grunt-contrib-jshint JSをシンタックスチェックするjshintを実行
grunt-contrib-watch ファイルの変更監視とタスクの実行、およびLiveReloadの実行
grunt-md5filename ファイル名のハッシュ難読化
grunt-phpunit PHPのユニットテストを行うphpunitを実行

 

それぞれの導入経緯はたとえばこんな感じでした。(一部フィクションです。伝えやすいように大げさにしてます。)

CSSの更新がマークアップエンジニアとゲーム開発エンジニアで衝突!

  • 【導入前】UI制作者がCSSを納品、それを開発エンジニアがリポジトリに追加。しかし緊急時には開発エンジニアがUIを制作、手っ取り早くデザインするためにインラインスタイルを書いてしまった
  • 【導入後】リポジトリ内でSass管理しGruntでCSSや圧縮CSSを生成。クラスを編集しても影響範囲等が明確で開発エンジニアが容易に(正しく)CSSを書けるようになった
  • grunt-contrib-compass, grunt-contrib-cssmin, grunt-contrib-csslint で実現

ゲームにJS多用でコードが複雑になり保守が大変!

  • 【導入前】それまでフィーチャーフォン版ゲームを作っていたがスマートフォンでJSを多用することに。JSerが作ったものの、開発エンジニアが保守しずらい
  • 【導入後】Coffeeの変換、JSファイルの結合、シンタックスチェック、ユニットテスト、難読化まで一度にできるになり、保守が楽になった
  • grunt-contrib-coffee, grunt-contrib-concat, grunt-contrib-uglify, grunt-contrib-jshint で実現

制作画像の圧縮を行う担当が画像種別(カード、アイテム、レイアウト、等)によりバラバラで管理も分散

  • 【導入前】いまある画像が圧縮済みかオリジナルか、等を把握するのが困難
  • 【導入後】画像の圧縮最適化タスクをGruntで自動化、管理しているので人為ミスがなくなった
  • grunt-imagemin で実現

ファイル名を隠蔽(ハッシュ化)したい

  • 【導入前】手動でスクリプトを回していた。うっかり忘れて事故につながることも
  • 【導入後】自動でやってくれるのでなにも考えなくて良くなった
  • grunt-md5filename で実現

PHPのユニットテストをしたい

  • 【導入前】手動でphpunitを叩いていた
  • 【導入後】ファイルの変更を監視して自動でphpunitが実行、エラーがあればGrowlで通知
  • grunt-contrib-watch, grunt-phpunit, grunt-notify で実現

毎回ビルドの度にコマンドを叩いてからじゃないとブラウザチェックができない

  • 【導入前】Sass-CSS変換やJSの難読化のコマンドを叩いてからブラウザで確認するまでに処理が終わるのを待たないといけない
  • 【導入後】ファイルの変更を監視してくれてGrowlでの通知もありLiveReloadもしてくれるので手間が省けた
  • grunt-contrib-watch, grunt-notify で実現

この他にもいろんな開発における痒いところにGruntプラグインは届いてくれるのです。

 

PHPでGruntを使う

npmで公開されているプラグインからPHP関連のものは2013/12/4時点で下記のとおりです。
過去30日間のダウンロード数の多い順に並べました。

Gruntプラグイン 内容 DL数
grunt-phpunit phpunit を実行 1077
grunt-phplint php -l を実行 735
grunt-php PHP の Built-in web server を実行 597
grunt-phpcs PHP_CodeSniffer を実行 445
grunt-php-set-constant 動的にPHPファイルdefineの内容を書き換えます 297
grunt-php-cs-fixer PHP Coding Standard Fixer を実行 274
grunt-php2html htmlをphpより生成 273
grunt-php-to-json PHPのArrayをJSONに変換 231
grunt-phpspec phpspec を実行 157
grunt-phpdocumentor phpdoc を実行 119
grunt-phpcpd PHP Copy/Paste Detector を実行 67
grunt-laravel-validator Generate PHP validations that use Laravel from JS descriptions of the input data format 54
grunt-phpmd PHP Mess Detector を実行 53
grunt-typo3-phpunit TYPO3 UnitTests を実行 47
grunt-php-analyzer Grunt interface to php-analyzer 39
chop-grunt-php-builder Grunt plugin to statically build PHP files 32
grunt-haml-php Process HAML templates using MtHaml, a PHP port of Haml. 32
grunt-jade-php grunt-jade-php 12
grunt-phptpl Processes PHP files (e.g. PHP templates) to static files. 8

(2013/12/4時点)

以上がPHPのキーワードでGruntpluginを検索したものです。
もちろんこれ以外にもWebゲーム開発において使えるプラグインは沢山眠っています。探すのもまた楽しいですよ! -> Grunt Plugins

他にも使えるGruntの便利どころ

Gruntを使い込んでいくと、あれもできるかも?これもできるかも?と、使いどころが見えてきます。
ぼくが使ったちょっと変わったTipsを一つご紹介します。

DocumentRootを分けて利用した話

 

Gruntでは気軽にファイル群を生成できるので、WebサーバでDocumentRootをスイッチして同じアセットファイルを参照してるいますが、

  • Webアプリケーションフレームワークを介すもの
  • 静的コンテンツを表示するもの

を分けて実際のゲームもモックHTMLも同時に確認できたり、

  • 本番デプロイする圧縮、難読、最適化されたアセットファイルを参照するもの
  • 開発デバッグしやすいようにオリジナルの見やすいアセットファイルを参照するもの

を分けて開発確認とリリースQA確認とを同時に吐き出せるようにして効率化を図っています。

カスタムタスクの定義のコツ

watch(grunt-contrib-watch) はコーディング中に変更のあったファイルを監視して自動でタスクを実行してくれるのでとても便利です。が、万能というわけではなく使いどころを気をつけないと無駄にタスクが走ってしまうことになります。
例えばcompass、cssmin、uglifyはwatchするけどjshintやphpunitは手動にしておく、など使い分けます。これによってタスク完了の待ち時間の調整ができます。
実はGruntのWatchはまだまだなところがあって、プラグインが対応していないと個別ファイルごとのWatchとタスク実行ができない場合が多くあります。

あとは、カスタムタスクの定義は役割(バックエンドエンジニア、HTMLマークアップエンジニア、アニメーションクリエイター、等)によって使いやすく分けると捗ります。

最後に

僕がGruntを入れるときはまだGREEではそんなに使われていませんでした。使っていたとしてもクリエイティブエンジニアが個人で使っていたりして限られていました。
この1年の間に急速に進化し、普及したと思います。今では日本でもブログで書かれたり講演のテーマになったり雑誌で紹介されたりしてとてずいぶんみかけるようになりました。

Gruntをチームに導入するにあたり、実はそれまではフロントエンドのエンジニアとバックエンドのエンジニアはリポジトリも別でスケジュールも別、フロントエンドで制作されたUIモックがバックエンドのエンジニアに納品され、それをリポジトリに組み込んでいく、という一方通行の作業でした。なのでもしUIの修正が必要になったらUI製作者へのフィードバックが大変でコンフリクトのコストもかかっていました。

しかし、Grunt導入とともにリポジトリに参加していただき、また、上記でDocumentRootを分けたことでUIモック開発とゲームアプリ開発を同期して開発を進めることができるようになり無駄を省き大きくコスト削減につながりました。それまでSassを扱えなかったプログラマがすぐに扱えるようにもなりました。

 

さて、今回はGruntをPHPでということでしたが、他の言語でも使えそうなプラグインも多数公開されています。もしくはこの機会にプラグインを作ってみてもいいかもしれません。
ソースを読んでいただくとわかりますが公式プラグインでさえ数行でできていて非常に簡単、シンプルに作ることができます。

そしてオープンソースとして公開(つまりnpmへ登録)も簡単にできますので、自慢のプラグインができたら是非公開しましょう。

 

Gruntについてもっと知りたい方は

等に実際の導入手引もありますのでご覧ください。

 

おまけ

せっかくクリスマスなので npm xmas を実行するGruntプラグインを作りました。ソースを見ていただければいかに簡単に作れちゃうかわかると思います。
エンジニアの皆様は是非これでクリスマスを乗り切って下さい!

grunt-xmas

animation

 

あしたは矢口裕也さんです!よろしくお願いしまーす!