ygoto3.com

Software engineer at CyberAgent.

grunt-angular-templatesを使ってみた

AngularJSのElement Directiveを使っていて

AngularJSのElement Directiveは便利でHTMLも綺麗になるので好きなんですが、テンプレートをDirectiveの中に書くのだけ好きになれません。

JavaScriptファイル内に文字列として書くためエディタのカラーリングも効かず、書くにくいのが嫌でした。

もちろんtemplateの代わりにtemplateUrlで外部HTMLを使うこともできますが、別途AJAXしてしまうので無駄にファイルのリクエスト数が増えてしまうのも好ましくありません。

よく使うテンプレートたちは外部HTMLで書いておいて、リクエスト数は抑えたい。

それの1つの解決方法として、今回はgrunt-angular-templatesを使いました。

grunt-angular-templatesとは

grunt-angular-templatesは、Eric Clemmons氏のGruntプラグインで、指定したHTMLファイル郡をミニファイ・結合して1つのJavaScriptファイルとして出力してくれます。

そのJavaScriptファイルには、指定したHTMLファイルを$templateCache.putするように記述してあるので、後はそのURLをtemplateUrlで指定すると別途AJAXすることなくキャッシュしたデータを使用してくれます。

インストール

インストールはnpm。

1
$ npm install grunt-angular-templates --save-dev

そしてGruntfile.jsでロードを有効化。

1
grunt.loadTasks('grunt-angular-templates');

設定

まずは一番シンプルな形を試します。 AngularJSのテンプレートとして書いたHTMLファイル全てを $templateCacheにキャッシュさせるJavaScriptを出力させます。

Gruntfile.jsで以下の最低限のオプションだけ記述します。

1
2
3
4
5
6
ngtemplates: {
myApp: { // angularのモジュール名に合わせます
src: 'templates/**/*.html',
dest: 'js/templates.js'
}
}

"myApp"はテンプレートを使うモジュール名に合わせます。

実行

実行します。

1
$ grunt ngtemplates

もし下記のような名前のHTMLファイルを入れていれば

1
2
3
templates
└── btnLike.html
└── btnFollow.html

js/templates.jsには以下のようなコードが出力されます。

1
2
3
4
5
6
7
8
angular.module('myApp').run(['$templateCache', function($templateCache) {
$templateCache.put('templates/btnFollow.html',
"<a href=# class=\"btn btn-large btn-follow\">Follow</a>"
);
$templateCache.put('templates/btnLike.html',
"<a href=# class=\"btn btn-primary\">Like</a>"
);
}]);

あとはこのjs/templates.jsを

1
<script type="text/javascript" src="js/templates.js"></script>

と読み込めば、btnLike.htmlとbtnFollow.htmlの内容は読み込まれてキャッシュされるので、 使うときは$routeProviderやDirectiveのtemplateUrlで

1
2
3
4
5
6
7
angular.module('myApp')
.directive('btnLike', function() {
return {
restrict: 'E',
templateUrl: 'templates/btnLike.html'
};
});

という感じで使うか、またはHTMLに直接

1
<div ng-include="’templates/btnLike.html’"></div>

とngIncludeで指定して使うことができます。

その他オプションを試してみる

もしテンプレートが置いてあるパスと実際にアプリ内で指定するURLが違う場合は、 cwdオプションを使って下記のようにカレントディレクトリを別途指定します。

1
2
3
4
5
6
7
8
// Gruntfile.js
ngtemplates: {
myApp: {
cwd: 'app', // 実際にtemplatesディレクトリが入っているパス
src: 'templates/**/*.html', // アプリで使うURL
dest: 'app/js/templates.js'
}
}

また、テンプレート用JSに変換する際にhtmlminを利用することができるので、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Gruntfile.js
ngtemplates: {
myApp: {
src: 'templates/**/*.html',
dest: 'js/templates.js'
options: {
htmlmin: { // htmlminと同じオプションを指定できる
collapseBooleanAttributes: true,
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true,
removeEmptyAttributes: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true
}
}
}
}

オプションでhtmlminを指定して出力時のファイルサイズを最適化できました。

grunt-angular-templatesのおかげでテンプレートの外部HTML化が実現し、リクエスト数を抑えることもできました。

grunt-angular-templates https://github.com/ericclemmons/grunt-angular-templates