Gruntfile.js に何を書くか？sails.jsでの利用方法を参考に ヽ(ﾟｰﾟ*ヽ)(ﾉ*ﾟｰﾟ)ﾉわぁい

この記事では以下の絵文字を大事な個所で使用中

 - :exclamation: 注意点
 - :boom: 予期せぬ例外やエラーメッセージ
 - :sunny: 解決方法・お役立ち情報

みなさん、こんにちはでス。sails.js、javascript関連でこんな

 - [最近のMV*フレームワークを分業体制/複数ベンダーのプロ管の視点から考えた](http://qiita.com/scleen_x_x/items/798eb5915f86bdb79134)
 - [ブラウザでjavascriptを書いて実行できるオープンソースの jsbin と plunker について調べたのでまとめたよ ヽ(ﾟｰﾟ*ヽ)(ﾉ*ﾟｰﾟ)ﾉわぁい](http://qiita.com/scleen_x_x/items/23223b492f7961d8e579)
 - [sails.js (0.10.x) 起動時にデータを自動的にロードして開発を効率化したい ヽ(ﾟｰﾟ*ヽ)(ﾉ*ﾟｰﾟ)ﾉわぁい | sails.js (0.10.x) で始めるアプリ開発](http://qiita.com/scleen_x_x/items/6e1808735ab1ac63a80e)
 - [sails.js (0.10.x) CORS を有効にしてよりオープンなAPIにする方法 ヽ(ﾟｰﾟ*ヽ)(ﾉ*ﾟｰﾟ)ﾉわぁい | sails.js (0.10.x) で始めるアプリ開発](http://qiita.com/scleen_x_x/items/891ffb40f6f2c9e781f9)

記事を書いているものです :smile: プロ管したり、開発環境整えたり、実際にコード書いたり、デザインしたりといろいろやってます。いろいろやっているので、できるだけみんながハッピーになるような仕組みをつくっていけたらいいと思う次第。デスマでお疲れの皆さんもこれを読んだら少し休んで :zzz: 横になってみましょう :imp:

# この記事の概要

 - grunt の定義ファイル Gruntfile.js が巨大化する問題
 - sails.js ではどのように解決しているか

の二つ

## 前提になる知識

### grunt

gruntはビルドに使ったり、もろもろのタスクを連続的に実行できる便利なツール http://gruntjs.com/

### sails.js

railsっぽいNode.jsのフルスタックフレームワーク http://sailsjs.org

# grunt の定義ファイル Gruntfile.js が巨大化する問題

便利なタスクの定義をGruntfile.jsというファイルに書くことができるものの、気づくと巨大化しているなんてことも。まぁ、「お前が書いたんだろ」と言われればそれまでですが :angry: ファイルが巨大化すると

 - 可読性が落ちる
 - メンテナンスしにくい

という欠点ばかりが目立ち

 - ファイル数が少ない

というけっこうどうでも良い利点がますます価値を失います。

他のウェブサイトでは

> シンプルなタスクであれば分かりやすいのですが、多くの拡張機能（プラグイン）を使用したり、タスクの制御を細かく行う必要が生じたたりした場合、Gruntfileの記述量が増えて冗長になり、タスク同士の関連やタスク実行結果も分かりにくくなってしまいます。

http://www.atmarkit.co.jp/ait/articles/1408/19/news035.html

と断言されていたり :fire:

> Grunt を使おうと思っていたら、最近は gulp の方が主流との話を目にする。どうやら gulp の方が記述を簡潔にできて可読性がよいそうな。というわけで、一度 Grunt で書いたものを gulp で書き直してみた。

http://create-something.hatenadiary.jp/entry/2014/07/26/094737

といった感じの噂がまことしやかに :imp:

無駄に長くなると、「あれ、やっべぇ、必要なところまで消しちゃった、まぢぃ」といったことが発生します。私はときどき、不要な個所を消したり、整理してもろもろの調整でたまったストレスを解消するために気分転換するのですが、全然気分転換になりません。

## :sunny: sails.js ではどのように解決しているか

 - 設定とタスクの登録を分けている
 - ファイルをできるだけ分割

といった感じ。具体的には

 - `tasks/config` と `tasks/register` というディレクトリを用意し、それぞれ設定とタスクの登録といった感じで整理しています。
 - `tasks/config` 内はタスク名毎の設定ファイルで作成
 - `tasks/register` 内はエイリアス毎にファイルを作成

このGruntfile.js自体は汎用的に使えるものなので、とても参考になると思います。

それでは良いgruntライフをお送りください :smile: ヽ(ﾟｰﾟ*ヽ)(ﾉ*ﾟｰﾟ)ﾉわぁい

### uglify.js の例

こんな感じで uglify の設定をして

```tasks/config/uglify.js
/**
 * Minify files with UglifyJS.
 *
 * ---------------------------------------------------------------
 *
 * Minifies client-side javascript `assets`.
 *
 * For usage docs see:
 * 		https://github.com/gruntjs/grunt-contrib-uglify
 *
 */
module.exports = function(grunt) {

	grunt.config.set('uglify', {
		dist: {
			src: ['.tmp/public/concat/production.js'],
			dest: '.tmp/public/min/production.js'
		}
	});

	grunt.loadNpmTasks('grunt-contrib-uglify');
};
```

こんな感じで`prod`として登録されます。

```tasks/register/prod.js
module.exports = function (grunt) {
	grunt.registerTask('prod', [
		'compileAssets',
		'concat',
		'uglify',
		'cssmin',
		'sails-linker:prodJs',
		'sails-linker:prodStyles',
		'sails-linker:devTpl'
	]);
};

```

### sails.js の Gruntfile.js

最新版はこっちかも⇒ https://github.com/balderdashy/sails/

```Gruntfile.js
/**
 * Gruntfile FTW!
 *
 * This Node script is executed when you run `grunt` or `sails lift`.
 * It's purpose is to load the Grunt tasks in your project's `tasks`
 * folder, and allow you to add and remove tasks as you see fit.
 * For more information on how this works, check out the `README.md`
 * file that was generated in your `tasks` folder.
 *
 * WARNING:
 * Unless you know what you're doing, you shouldn't change this file.
 * Check out the `tasks` directory instead.
 */

module.exports = function(grunt) {


	// Load the include-all library in order to require all of our grunt
	// configurations and task registrations dynamically.
	var includeAll;
	try {
		includeAll = require('include-all');
	} catch (e0) {
		try {
			includeAll = require('sails/node_modules/include-all');
		}
		catch(e1) {
			console.error('Could not find `include-all` module.');
			console.error('Skipping grunt tasks...');
			console.error('To fix this, please run:');
			console.error('npm install include-all --save`');
			console.error();

			grunt.registerTask('default', []);
			return;
		}
	}


	/**
	 * Loads Grunt configuration modules from the specified
	 * relative path. These modules should export a function
	 * that, when run, should either load/configure or register
	 * a Grunt task.
	 */
	function loadTasks(relPath) {
		return includeAll({
			dirname: require('path').resolve(__dirname, relPath),
			filter: /(.+)\.js$/
		}) || {};
	}

	/**
	 * Invokes the function from a Grunt configuration module with
	 * a single argument - the `grunt` object.
	 */
	function invokeConfigFn(tasks) {
		for (var taskName in tasks) {
			if (tasks.hasOwnProperty(taskName)) {
				tasks[taskName](grunt);
			}
		}
	}




	// Load task functions
	var taskConfigurations = loadTasks('./tasks/config'),
		registerDefinitions = loadTasks('./tasks/register');

	// (ensure that a default task exists)
	if (!registerDefinitions.default) {
		registerDefinitions.default = function (grunt) { grunt.registerTask('default', []); };
	}

	// Run task functions to configure Grunt.
	invokeConfigFn(taskConfigurations);
	invokeConfigFn(registerDefinitions);

};

```