Gruntによるリソース軽量化TIPS

おもにGruntを使ったチューニング手法をまとめてみました

# スピード計測

## PageSpeed Insights
https://developers.google.com/speed/pagespeed/insights/?hl=ja
Googleの計測サービス
良い点と悪い点を出してくれます
最適化されたリソースの提供もしてくれます

# Gruntを使用したリソース軽量化
nodeを使ったタスクランナーであるGruntを使ったリソースの軽量化TIPS

Gruntインストール

```bash:
$ npm i grunt --save-dev
```
Gruntfile.jsを作成

```javascript:Gruntfile.js
module.exports = function(grunt) {
	// タスクの設定
	grunt.initConfig({});
	// プラグインのロード
	grunt.loadNpmTasks('');
	// タスクの登録
	grunt.registerTask('default', ['']);
};
```

## grunt-uncss
https://github.com/addyosmani/grunt-uncss
htmlから使用しているCSSのみを抽出してくれるプラグインです

インストール

```bash:
$ npm i grunt-uncss --save-dev
```

Gruntfile.jsの設定

```javascript:Gruntfile.js
module.exports = function(grunt) {
	grunt.initConfig({
		uncss: {
			dist: {
				files: {
					'./build/all.css': ['./src/index.html']
				}
			}
		}
	});
	
	grunt.loadNpmTasks('grunt-uncss');

	grunt.registerTask('css_min', ['uncss']);
};
```

テスト用のhtmlとcss
わざと不要なプロパティを用意しました

```html:index.html
<!DOCTYPE html>
<html>
<head>
	<title>test</title>
	<link rel="stylesheet" type="text/css" href="test.css">
</head>
<body>
<h1 class="title">test title</h1>
<p class="test">test description</p>
</body>
</html>
```
.hogeクラスの記述はindex.htmlでは使われていないので不要です

```css:test.css
.title {
  background-color: red;
}

.hoge {
  font-size: 30px;
}

.test {
    float: left
}
```

タスク実行

```bash:
$ grunt css_min
```

結果、不要なプロパティが削除されたall.cssが出来上がります

```css:all.css
/*** uncss> filename: src/test.css ***/

.title {
  background-color: red;
}

.test {
  float: left;
}
```

## grunt-csso
https://github.com/t32k/grunt-csso
cssのコメントやスペース・改行を削除して、軽くしてくれるプラグインです

インストール

```bash:
$ npm i grunt-csso --save-dev
```

Gruntfile.jsの設定

```javascript:Gruntfile.js
module.exports = function(grunt) {
	grunt.initConfig({
		csso: {
			dist: {
				files: {
					'./build/all.min.css': ['./build/all.css']
				}
			}
		}
	});
	
	grunt.loadNpmTasks('grunt-csso');

	grunt.registerTask('css_min', ['csso']);
};
```

実行
先ほど作成したall.cssを圧縮したいとおもいます

```bash:
$ grunt css_min
```

結果、無駄なスペース・改行を取り除くことが出来ました

```css:all.min.css
.title{background-color:red}.test{float:left}
```

# grunt-contrib-concat
https://github.com/gruntjs/grunt-contrib-concat
複数のjsを一つのファイルにまとめてくれるプラグインです

インストール

```bash:
$ npm i grunt-contrib-concat --save-dev
```
Gruntfile.jsの設定

```javascript:Gruntfile.js
module.exports = function(grunt) {
	grunt.initConfig({
		concat: {
			files: {
				src: [
					'./src/test.js',
					'./src/hoge.js'
				],
				dest: './build/all.js'
			}
		}
	});
	
	grunt.loadNpmTasks('grunt-contrib-concat');

	grunt.registerTask('js_min', ['concat']);
};
```

テスト用ファイル
test.jsとhoge.jsをつなぎ合わせます

```javascript:test.js
;(function() {
	document.addEventListener('DOMContentLoaded', function() {
		console.log('test.js');
	}, false);
})();
```

```javascript:test.js
;console.log('hoge');
```

実行

```bash:
$ grunt js_min
```
2つのファイルがつなぎ合わされたファイルができあがります
たまにファイルの終端に;が入っていないファイルなどがあって実行時にエラーになったりするので注意が必要です

```javascript:all.js
;(function() {
	document.addEventListener('DOMContentLoaded', function() {
		console.log('test.js');
	}, false);
})();
;console.log('hoge');
```

## grunt-contrib-uglify
https://github.com/gruntjs/grunt-contrib-uglify
jsのコメントやスペース・改行を削除して、軽くしてくれるプラグインです


インストール

```bash:
$ npm i grunt-contrib-uglify --save-dev
```
Gruntfile.jsの設定

```javascript:Gruntfile.js
module.exports = function(grunt) {
	grunt.initConfig({
		uglify: {
			dist : {
				files : {
					'./build/all.min.js' : ['./build/all.js']
				}
			}
		}
	});
	
	grunt.loadNpmTasks('grunt-contrib-uglify');

	grunt.registerTask('js_min', ['uglify']);
};
```
実行
先ほど作成したall.jsを圧縮したいと思います

```bash:
$ grunt js_min
```

結果
圧縮されたall.min.jsが出来上がります

```javascript:all.min.js
!function(){document.addEventListener("DOMContentLoaded",function(){console.log("test.js")},!1)}(),console.log("hoge");
```

## grunt-contrib-htmlmin
https://github.com/gruntjs/grunt-contrib-htmlmin
htmlのコメントやスペース・改行を削除して、軽くしてくれるプラグインです

インストール

```bash:
$ npm i grunt-contrib-htmlmin --save-dev
```
Gruntfile.jsの設定

```javascript:Gruntfile.js
module.exports = function(grunt) {
	grunt.initConfig({
		htmlmin : {
			dist : {
				options : {
					removeComments : true,
					collapseWhitespace : true,
					minifyJS : true,
					minifyCSS : true
				},
				files : {
					'./build/index.min.html' : './src/index.html'
				}
			}
		}
	});
	
	grunt.loadNpmTasks('grunt-contrib-htmlmin');

	grunt.registerTask('html_min', ['htmlmin']);
};
```
実行
先ほどのindex.htmlを圧縮したいと思います

```bash:
$ grunt html_min
```

結果

```html:index.html
<!DOCTYPE html><html><head><title>test</title><link rel="stylesheet" type="text/css" href="test.css"></head><body><h1 class="title">test title</h1><p class="test">test description</p></body></html>
```

## grunt-contrib-watchでビルドを自動化
https://github.com/gruntjs/grunt-contrib-watch
ファイルを監視して、変更があったら自動でタスクを走らせるプラグインです
せっかくなので、上記で紹介した全てのプラグインを走らせるようにしてみたいと思います

インストール

```bash:
$ npm i grunt-contrib-watch --save-dev
```

Gruntfile.jsの設定
src配下のファイルに変更があった場合、全てのタスクを走らせます

```javascript:Gruntfile.js
watch : {
	options : {
		livereload : true
	},
	watch_all: {
    	files: ['./src/**/*'],
    	tasks: ['uncss', 'csso', 'concat', 'uglify', 'htmlmin']
    }
}

```

```bash:
$ grunt watch
```

監視中

```bash:
Running "watch" task
Waiting...
```

src配下のファイルに変更を加えると以下のように全てのタスクが走ります

```bash:
>> File "src/index.html" changed.
Running "uncss:dist" (uncss) task
File ./build/all.css created: 162 B → 134 B

Running "csso:dist" (csso) task
true
File ./build/all.min.css created.

Running "concat:files" (concat) task
File ./build/all.js created.

Running "uglify:dist" (uglify) task
>> 1 file created.

Running "htmlmin:dist" (htmlmin) task
Minified 1 files

Done, without errors.
Completed in 3.304s at Sat Nov 14 2015 16:50:52 GMT+0900 (JST) - Waiting...
>> File "src/test.js" changed.
Running "uncss:dist" (uncss) task
File ./build/all.css created: 162 B → 134 B

Running "csso:dist" (csso) task
true
File ./build/all.min.css created.

Running "concat:files" (concat) task
File ./build/all.js created.

Running "uglify:dist" (uglify) task
>> 1 file created.

Running "htmlmin:dist" (htmlmin) task
Minified 1 files

Done, without errors.
Completed in 3.289s at Sat Nov 14 2015 16:51:12 GMT+0900 (JST) - Waiting...
```

# 画像の圧縮
webパフォーマンス向上において画像の容量削減は重要です
## ImageOptim
https://imageoptim.com/
もうかなり有名で手軽に画像を圧縮するソフトといえばこれがよくでてきます
データをドラッグアンドドロップすることでディレクトリ構造などを保持したまま一気に圧縮してくれます
画像に含まれるメタデータなども削除してくれるので結構圧縮率がよいです

## grunt-image
https://www.npmjs.com/package/grunt-image
画像を圧縮してくれるgruntプラグインです
インストール

```bash:
$ npm install --save-dev grunt-image
```

Gruntfile.jsの設定
src配下の全ての画像をbuild配下に圧縮して書き出します

```javascript:Gruntfile.js
image: {
	static: {
		options: {
			pngquant: true,
			optipng: false,
			zopflipng: true,
			advpng: true,
			jpegRecompress: false,
			jpegoptim: true,
			mozjpeg: true,
			gifsicle: true,
			svgo: true
		},
		files: {
				'./build/img.png': 'src/img.png',
				'./build/img.jpg': 'src/img.jpg',
				'./build/img.gif': 'src/img.gif',
				'./build/img.svg': 'src/img.svg'
			}
		},
		dynamic: {
			files: [{
			expand: true,
			cwd: 'src/',
			src: ['**/*.{png,jpg,gif,svg}'],
			dest: './build/'
		}]
	}
}
```

実行

```bash:
$ grunt image
```

# サンプルプロジェクト
こちらにおきました
<a href="https://github.com/SatoshiKawabata/GruntWebTuning">サンプルプロジェクト</a>