快適アプリ開発Backbone.Marionette 第1回 Backbone.Marionetteとは
第1回目はBackbone.Marionetteはどのようなものか、その特徴や機能を概観します。Backbone.jsを使う際に頻出する機能を補完するライブラリなので、Webアプリ開発の効率が上がります。
- カテゴリー
- JavaScript >
- Backbone
発行
はじめに
本シリーズではBackbone.Marionetteについて取り上げます。Marionette、操り人形という言葉から思い浮かぶように、Backbone.jsに新たな機能を追加するライブラリです。Backbone.jsを利用したアプリケーション開発にどのような変化をもたらすのか、その上でアプリケーション設計をどのように行うのかを解説していきます。
なお、このシリーズは、Backbone.jsを使ったことがある方を想定して書かれています。Backbone.jsにまったく触れたことのない方は「Webアプリ構築のためのBackbone.js入門」シリーズなどを参考にしてもらえればと思います。
Marionette.jsとは
執筆現在(2014年2月中旬)の最新バージョンは1.6.1。
Marionette.jsとは、簡単に言うとBackbone.jsを利用したアプリケーション開発をもっと楽にしてくれるライブラリです(以下、Backbone.MarionetteをMarionette.jsと表記していきます)。
Backbone.jsは、すでにWebアプリケーションのフロントエンド実装のためのライブラリとして広く利用されています。クライアントサイドMVCの慣習に沿ってオブジェクトを分類し、それらが相互に作用し合って、アプリケーションの要求を満たしていくという設計を促すためのシンプルな指針を提供しています。
しかし、そのシンプルさゆえに、アプリケーション全体を統括するような仕組みや大規模化していくコードを、きれいに保つための仕組みまでは提供していません。そういった部分は、それぞれの開発者たちに委ねられています。これは状況に応じて柔軟な対応が取れるという点では、よいことですが、特にViewにおいては毎回同じようなコードを書いてしまうような場面もあります。
そこでMarionette.jsは、多くの場合に有効な実装パターンを取り込んで、開発者たちがこれから作るアプリケーションのためのコードに集中できる時間を増やすことを目指しています。さらにアプリケーション全体を管理する機能も加えることで、より大きな規模のアプリケーションを、もっと楽に作るためのライブラリとして公開されています。
Marionette.jsの構成要素
まずはMarionette.jsでできることを構成要素を見ながら概観してみましょう。Marionette.jsは主に次のような機能を提供します。
名前 | 役割 |
---|---|
Marionette.Application | アプリケーション全体の実行を管理する |
Marionette.AppRouter | URLに対する処理を行う |
Marionette.Controller | モジュール同士を繋ぐなど汎用的な役割を担う |
Marionette.ItemView | 1つのModelをViewとして扱う |
Marionette.CollectionView | Collectionを扱いItemViewを子Viewとして管理する |
Marionette.CompositeView | CollectionViewを継承し、より柔軟なDOMツリー構造を扱う |
Marionette.Region | DOM要素をViewをレンダリングするためのコンテナとして定義する |
Marionette.Layout | 複数のRegionとViewを管理する |
それぞれ、このシリーズの後続の回で詳しく触れていきますが、Application
、AppRouter
、Controller
はViewやModelの間を取り持つ機能を担っています。ItemView
、CollecttonView
、CompositeView
、Region
、Layout
はそれぞれ異なった役割で、View周りのコーディングに役立つ機能を持っています。
Marionette.jsにできること
Marionette.jsから得られる恩恵は大小さまざまで、細かいものを挙げていくときりがないほどですが、大きなものを挙げるとすれば、次のような点があります。
- モジュール化のサポート
- 開発者が書かなければならないコード量の減少
- 機能の部分的な利用
モジュール化のサポート
Marionette.jsの機能の中で大きなものとして、モジュール化のサポートがあります。モジュール化というのは、ある機能を表す抽象的なまとまりにソースコードを分解することです。
大規模なWebアプリケーションをきれいなコードに保ちながら作っていくためには、複雑な機能を細かな機能に分解して、その役割を果たすモジュールとして組み合わせていくことが大事です。また、それぞれのモジュールが自立できるように、互いにメソッドを直接呼び出したりといった依存関係は取り除いていく必要があります。
自立した小さなモジュールを保つことでテストもしやすくなり、たくさんのモジュールを組み合わせた大規模なアプリケーションを作ることができます。
Marionette.jsはそのモジュール化を助けるための、モジュールの定義と管理、そしてモジュール同士を連携させるためのイベントやメッセージングの機能を備えています。
次のコードはアプリケーション全体を管理するMarionette.Application
オブジェクトのインスタンスにListモジュールを定義して、アプリケーションを開始する例です。
// Marionette.Applicationインスタンスを作成
var Todo = new Marionette.Application();
// Todo.Listモジュールを定義
Todo.module('List', function(List, Todo, Backbone, Marionette, $, _) {
// Todo.Listモジュールの初期化コードを記述
List.addInitializer(function() {
alert('List.addInitializerから呼ばれました。');
});
});
// アプリケーションの開始
Todo.start();
Todo.start()
でアプリケーションを開始すると、Todo
アプリケーションのモジュールであるTodo.List
を定義するコードの中に書かれたaddInitializer
メソッドに渡されている初期化処理も併せて実行されます。
これはほんの一例ですが、こうしてアプリケーションの開始に連動する初期化処理もモジュールを定義するコード自身の中に記述することで、コードの見通しをよくすることができます。
コード量を減らす
Marionette.jsはBackbone.jsによるアプリケーション開発におけるいくつかの便利な実装パターンをすでに取り込んでいます。
入れ子になるViewを扱う仕組みや、いくつかのイベントの追加などは、もしかしたらたいていのプロジェクトで、Backboneオブジェクトをベースにした同じようなカスタムオブジェクトが作られているかもしれません。そうしたよく必要とされる機能はMarionette.jsの方ではじめから用意されています。
ほかにも、Viewインスタンスを破棄する際のメモリリークの防止や、HTMLテンプレートとModelのデータを合わせてDOMツリーへ追加し、レンダリングを行うといったような処理も、ある程度自動的に行ってくれるようになっています。
このような機能があると、アプリケーションを作ろうとしたときに、開発者が自分たちで用意すべきコードの量というのは減ります。それらの汎用的な機能はMarionette.jsが担当する仕事となるので、その整備に煩わされることなく、自分たちのアプリケーションが果たすべき要求に集中して取り組むことができるようになります。
次のコードは簡単な例ですが、Backbone.Viewを継承したクラスによくあるrender
の実装です。
var SampleView = Backbone.View.extend({
...
render: function() {
var template = $('#template');
var data = this.model.toJSON();
var html = _.template(template, data);
this.$el.html(html);
return this;
}
...
});
このような決まりきったパターンはMarionetteのViewに、すでに実装されているので、このパターンに沿っている限りは、render
メソッドの実装をこちらで書かなくてもかまいません。
次のコードではViewとして1つのModelを扱うMarionette.ItemViewを継承したクラスを定義しています。template
に渡しているのはscript
要素で書かれたテンプレートのIDセレクタです。
var Contact = Backbone.Marionette.ItemView.extend({
el: '#contact-region',
template: '#contact-template'
});
HTMLはこのようになっているとします。
<div id="contact-region"></div>
<script type="text/template" id="contact-template">
<dl>
<dt>Name</dt>
<dd><%- name %></dd>
<dt>Age</dt>
<dd><%- age %></dd>
</dl>
</script>
そしてMarionette.ItemViewのインスタンスにModelを渡してrender
メソッドを実行するだけで、テンプレートを取得してModelのデータも適用してDOMツリーに挿入するところまでしてくれます。
var Person = Backbone.Model.extend({
defaults: {
name: 'Alice',
age: 20
}
});
var person = new Person();
var contact = new Contact({
model: person
});
contact.render();
部分的な導入が可能
Marionette.jsのそれぞれの機能もまた、自立したモジュールとして互いに依存せずに、必要な場合に連携して働くように設計されています。
そのため、Marionette.jsを導入するにあたっては、先に挙げたMarionette.jsの機能のすべてを一度に導入する必要はなく、何か大きなルールに従うことになるということは起こりません。Marionette.jsのすべての機能について、あらかじめよく知っておかなければならないということもありません。
例えばMarionette.ItemView
や、Marionette.CollectionView
は使うけれど、Marionette.Application
は使わないといった選択をすることができます。そのときには、Marionette.ItemView
とMarionette.CollectionView
の仕組みについて知っておけば、まずは十分なのです。
したがって、自分たちのプロジェクトの中で、すでに確立した手法があれば、それをベースにして一部分だけMarionette.jsを取り入れたり、既存のBackbone.jsアプリケーションのコードを徐々にMarionette.js化していくようなこともできるだろうと思います。
Marionette.jsの使い方
Marionette.jsはBackbone.jsとその依存関係に加えて、Backbone.WreqrとBackbone.BabySitterに依存していますが、公式サイトからPre-packagedアーカイブをダウンロードすれば、必要なライブラリはすべて揃います。
Marionette.js - Downloads and Documentation
ダウンロードしたアーカイブを展開したら、backbone.marionetteフォルダ直下にあるファイル*を次のように読み込みます。
*注:直下にあるファイル
アーカイブを解凍したbackbone.marionetteフォルダ直下以外に、coreフォルダや、amdフォルダにもbackbone.marionette.jsファイルがありますが、こちらではありません。
<script src="jquery.js"></script>
<script src="underscore.js"></script>
<script src="backbone.js"></script>
<script src="backbone.marionette.js"></script>
Backbone.WreqrとBackbone.BabySitterはbackbone.marionette.jsのファイルに含まれていますので、明示的に読み込む必要はありません。
同梱されているjson2.jsライブラリは、古いバージョンのブラウザに対応する必要がある場合に読み込みます。
参考になるWeb上の文書
Marionette.jsについての文書は次に紹介するURLからも参照することができます。
リポジトリのdocsディレクトリにMarionette.jsが提供する各コンポーネントの解説があります。
GitHub Wiki ページも用意されています。
注釈付きのソースコードを読むこともできます。
Marionette.jsの作者、Derick Bailey氏によるアプリケーションサンプルと、そのGitHubリポジトリも参考になります。
まとめ
今回はMarionette.jsの概要について解説しました。次回から具体的なMarionette.jsの機能や使い方の解説をしていきます。