Backboneのテンプレート開発は、Grunt使ってJSTに変換すると捗る
Backbone使うときにちょっと考えないといけないのが、テンプレートをどこに書くかという問題です。
「ToDoアプリを作ってみよう!」的なチュートリアルは、大抵、Underscore.jsのテンプ レートをindex.htmlのなかに書いていくパターンが多いかと思います。
こんな感じに。
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>Backbone Tutorial</title> </head> <body> ... <script type="text/template" id="item-template"> ... </script> ... </body> </html>
Backboneからは以下のように、jQueryを使ってテンプレート化します。
var itemView = Backbone.View.extend({ ... template: _.template($('#item-template').html()), ... });
これ、テンプレートが少ないうちはいいのですが、多くなってくると管理が大変です。
テンプレートはテンプレートとして別のファイルに分けて開発したくなりますね。
かと言ってファイルが多くなると、それはそれでhtmlから読み込むのが面倒だったり。。
Railsとか使っていると、Backboneのgemを入れればそのへんの環境もまとめて整えてくれるのですが、クライアントサイドだけだと自分で環境を整えないといけません。
という状況で、Gruntが活躍してくれました。
プラグインのインストール
今回はcontrib-jstというプラグインを使いました。(次はcontrib-handlebarsを使ってみようと思います)
まずはそいつをインストールします。
$ npm install grunt-contrib-jst --save-dev
Gruntの環境がない方はこちらを参照
テンプレート用ディレクトリの準備
今回は以下のようなディレクトリ構成にしました。
|-- build | |-- images | |-- javascripts # ここにJSTファイルが置かれる | |-- stylesheets | `-- index.html |-- src | |-- images | |-- javascripts | |-- stylesheets | |-- templates # ここにテンプレートファイルを置いておく | `-- index.html |-- Gruntfile.js
Gruntfile.jsの編集
Gruntfile.jsというファイルをルートディレクトリに作成し、以下のように編集します。
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), jst: { compile: { options: { templateSettings: { interpolate : /\{\{(.+?)\}\}/g }, processName: function(filename) { return filename.replace(/(src\/templates\/|.html)/g, ''); } }, files: { 'src/javascripts/templates/templates.js': [ 'src/templates/**/*.html' ] } } } }); grunt.loadNpmTasks('grunt-contrib-jst'); }
これで環境は整いました。
src/templates
以下に .html
という拡張子をつけてUnderscore.jsのテンプレート入れておけば、まとめてJSTファイルにしてくれます。
(今回は.html
という拡張子をつけるようにしましたが、.tpml
でも何でもいいと思います)
ワークフロー
たとえば、hello.html
を置いてコマンドを実行すると、build/javascripts
以下にtemplates.js
というファイルが作成されます。
$ grunt jst
htmlでtemplates.jsを読み込んでおけば、Backboneからは以下のようにしてテンプレート使うことができます。
var helloView = Backbone.View.extend({ template: JST['hello'], render: function() { this.setElement(this.template()); return this; } });
これですっきり!