[Grails]Asset-Pipelineプラグインのメモ

# 参考
[http://bertramdev.github.io/asset-pipeline/guide/introduction.html](http://bertramdev.github.io/asset-pipeline/guide/introduction.html)
[http://d.hatena.ne.jp/mottsnite/20140521/1400684993](http://d.hatena.ne.jp/mottsnite/20140521/1400684993)

# 概要
Grails2.4から、静的リソース（JavaScriptとCSSとか）の管理は、Resourceプラグインから、Asset-Pipelineがデフォルトになりました！
とのことですが、今一よく分からない。
なんだAsset-Pipelineって。。。
そもそもResourceプラグインもよくわかっていなかったのに。。。
ということで実際にAsset-Pipelineを触ってみました。

# Asset-Pipelineって？
公式ドキュメントによると、RubyOnRailsのAsset-Pipelineに似ているそうです。
でも俺RubyOnRails知らない。。。出鼻をくじかれまくりです。

+ アセット（静的リソースのこと？）の変更はすぐに反映されるよ。
+ `grails war`を実行すると、その時点でassetsをコンパイルするから、本番環境のブート時間が短縮されるよ。
+ Asset-Pipelineプラグインは、圧縮、縮小、キャッシュ機能を内蔵してるよ
+ Grailsの開発モードでのデバッグも簡単。だってまだ静的リソースは分かれてるからね。
+ マニフェストとタグリブはシンプルだよ。詳細はドキュメントを読んでね。

ということが公式の概要に書かれていました。

#メモ
Grails2.4.1で新規にアプリケーションを作ると、確かに以下のようなディレクトリができている。

```
k-kuwana% pwd
/home/k-kuwana/IdeaProjects/assetsample/grails-app/assets
k-kuwana% ls
images  javascripts  stylesheets
k-kuwana%                                                                                                                         
```

今後は、この **grails-app/assetsの各ディレクトリ配下にJavaScriptとCSSとかを配置していくらしい。**

で、デフォルトである程度ファイルが生成されているけど、その中でapplication.jsとapplication.cssが味噌らしい。このファイルがマニフェストと呼ばれるものらしい。
デフォルトだと以下のようになっています。

```css:grails-app/assets/stylesheets/application.css
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS file within this directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the top of the
* compiled file, but it's generally better to create a new file per style scope.
*
*= require main
*= require mobile
*= require_self
*/
```

```javascript:grails-app/assets/javascripts/application.js
// This is a manifest file that'll be compiled into application.js.
//
// Any JavaScript file within this directory can be referenced here using a relative path.
//
// You're free to add application-wide JavaScript to this file, but it's generally better 
// to create separate JavaScript files as needed.
//
//= require jquery
//= require_tree .
//= require_self

if (typeof jQuery !== 'undefined') {
	(function($) {
		$('#spinner').ajaxStart(function() {
			$(this).fadeIn();
		}).ajaxStop(function() {
			$(this).fadeOut();
		});
	})(jQuery);
}
```

#試す
とりあえずHelloコントローラとそれのindex.gspを用意する。

コントローラは普通。

```groovy:grails-app/controllers/assetsample/HelloController.groovy
package assetsample

class HelloController {

    def index() { }
}
```

View(gps)でassetタグリブを使って、application.(js|css)を読み込んでみる。

```html:grails-app/views/hello/index.gsp
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
  <asset:stylesheet href="application.css" />
  <asset:javascript src="application.js" />
  <title></title>
</head>
<body>
Hello World!
</body>
</html>
```


これで、http://localhost:8080/assetsample/hello/index にアクセスして、HTMLソースを見てみるとなんか定義していないCSSとJavaScriptが読み込まれてるぞ。。。！？
どうやらマニフェスト（application.js、appliation.css）に定義したファイルを自動で読み込んでくれるみたいだ。
で、概要に書いたとおりwarに固めるときに全部を一つのファイルに圧縮してくれるのか！
なんとなくわかってきたぞ。
ちなみに名前ってapplication.(css | js)じゃないとダメなの？確認してみる。

まず、`grails-app/assets/javascripts/application.js` をコピーして`grails-app/assets/javascripts/application2.js`を作成する。
で、application2.jsの中身を以下のように変更。

```javascript:grails-app/assets/javascripts/application2.js
console.log("application2.js! yeah!!!!!!");
```

中身をconsole.logのみにしてみた。
早速index.gspでこのapplication2.jsを読み込んでみる。

```html:grails-app/views/hello/index.gsp
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
  <asset:stylesheet href="application.css" />
  <asset:javascript src="application2.js" />
  <title></title>
</head>
<body>
Hello World!
</body>
</html>
```

で、再度http://localhost:8080/assetsample/hello/index にアクセスすると読み込まれているJavaScriptがapplication2.jsになって、ブラウザのJavaScriptコンソールにもちゃんとメッセージが出力されているはず。
でもjQueryが読み込まれてなくなっている。。。ということは、今回削除したrequireから始まる３行のコメントがjQueryを読み込む宣言だったっぽいですね。

#画像に関して
assetsディレクトリ配下にはimagesディレクトリもあります。
そう、画像もどうやら管理できるようです。
デフォルトだと、画像のURLは `assets/画像ファイル名`になります。
たとえば、デフォルトで用意されるGrailsの`apple-touch-icon.png`にブラウザからアクセスする場合はhttp://localhost:8080/assetsample/assets/apple-touch-icon.png となります。
gspで表示させる場合は`<asset:image src="apple-touch-icon.png" />`みたいな感じになります。
なお、HTML的には`<img src="/assetsample/assets/apple-touch-icon.png">`という感じで絶対パスになります。

#アセットとディレクティブについて
アセットパイププラグインは、 **ディレクティブ(Directives)** という独自構文を使って、ロード順序の指定とかきめ細かくアセットを管理できるよ！とのことです。

ディレクティブには以下の５つが有ります。

|ディレクティブ|役割|
|------------|----|
|require|一つのファイルを読み込む（相対パスで指定）|
|require_tree|指定したディレクトリを再帰的に読み込む（相対パスで指定）|
|require_self|自分自身（マニフェストファイル自身）を読み込む|
|require_full_tree|require_treeの強化版。アセットをすべてのプラグインからも再帰的に読み込む。|
|encoding|アセット（静的リソース）の文字コード|

`reuqire`については、態々拡張子を書く必要は無くて、例えばhoge.jsの場合なら`require hoge`とかけます。
`require tree`は、指定したディレクトリを再帰的にチェックして、すべてのファイルを読み込みます。なお、 **grails-app/assetsからの相対パス** で指定します。
`require_self`は、マニフェストファイル本体です。なので、別にこのディレクティブを書かなくても自動的にマニフェストファイルを読み込んでいるビューのheadタグの末尾で自動的にこのマニフェストファイルが読み込まれます。
require_selfを使うことで、マニフェストファイル本体が読み込まれる順番が制御できます。

このディレクティブを記述しているファイルを **マニフェスト** と呼ぶみたいですね。
application2.jsで試したとおり、ファイル名はどうでも良くて、ちゃんとディレクティブが書かれているか？が大切なんですね。

#実際に試してみる！
以下のJavaScriptファイルをテスト用に用意する。

```js:grails-app/assets/javascripts/hoge.js
console.log("This is hoge.js");
```
grails/assets/javascriptsの下にoriginalというディレクトリを作って、更に以下の２つのJavaScriptを作成。

```js:grails-app/assets/javascripts/original/original1.js
console.log("This is original1.js")
```

```js:grails-app/assets/javascripts/original/original2.js
console.log("This is original2.js")
```

そしてapplication2.jsを以下のように修正

```js:grails-app/assets/javascripts/application2.js
//= require hoge
//= require_self
//= require_tree ./original

console.log("application2.js! yeah!!!!!!");
```

これで再度http://localhost:8080/assetsample/hello/index にアクセスしてJavaScriptコンソールを確認すれば、実行結果が以下のようになっています。

```
This is hoge.js hoge.js
application2.js! yeah!!!!!!
This is original1.js
This is original2.js 
```

ということはディレクティブの宣言の順番でちゃんとJavaScirptが読み込まれていますね。

#まとめ
Grails2.4以降はJavaScipt、CSSや画像といった静的リソースの管理はAsset-Pipelineプラグインで行います。（行 **え** ます。当然強制ではない）
JavaScriptとCSSの場合、マニフェストというテキストファイルを用意してそれらを管理します。
マニフェストの中で、読み込むJavaScript、CSSや、その順番を定義します。
実際のビュー（gsp、layout、template）では、作成したマニフェストをassetタグリブを使って読みこむだけで、マニフェストで制御された通りにすべてのJavaScript、CSSファイルを自動的に読み込みます。
また、本番環境へのデプロイ（grails war）の場合は、JavaScriptやCSSは一つのマニフェストファイルの中に圧縮されます。

#所感
正直JavaScriptとかCSSが一つに圧縮される！とかってあまり興味が無いのでこのプラグイン自体は自分にとってはあまりこうパッとしないな〜と。。。
ただ、「よくわかんないけどこうするみたい」っていうのがあるとストレスがマッハなので今回Asset-Pipelineについて調べてみました。