BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ アーティクル HTML5とJavascriptによるモバイルアプリケーションアーキテクチャ

HTML5とJavascriptによるモバイルアプリケーションアーキテクチャ

ブックマーク

原文(投稿日:2012/09/18)へのリンク

もしあなたがエンドユーザーの携帯性への要求を抑えることができる、と考えているなら次のことを思い出して欲しい。PCが最初に導入された時に、IT部門はそれらをよせつけないようにした。それが上手く行ったか?モバイルデバイスの急増によって、IT部門は変わることを強いられている。今や彼らは、モバイルデバイスをサポートしなければならないし、更にそれは、モバイルフレンドリなアプリケーションの開発を必要とする程に広がっている。ユーザーが益々精通してくると、単に既存のアプリケーションをモバイルブラウザーでアクセスできるだけでは、満足できない。

モバイルアプリケーション向けのリッチなユーザーインタフェースを提供することは、ネイティブでもHTML5 とJavaScriptを使ってもできる。ネイティブアプリケーションは、リッチなユーザー体験を提供できるが、複数のデバイスOS向けにネイティブアプリケーションを作成するのは、時間がかかるし、高く付く。HTML5 とJavaScriptがデバイス非依存のユーザーインタフェースにチャンスを与えている。すなわち、HTML5要素を使って対話式のユーザーインターフェース部品をレンダリングするJavaScriptコンポーネントライブラリを使うことで、ユーザーインターフェースを作ることができる。HTML5には、移植性とリッチユーザーインターフェース開発をサポートする多くの新しいフィーチャがある。

この記事では、リッチなクライアントサイドの JavaScript / HTML5ベースのモバイルアプリケーションを実装するのに使われるフレームワークと構造を見ていくことにする。ユーザーインターフェースとナビゲーション要素は、全てブラウザ常駐の要素であり、一方アプリケーションが提供する唯一の役割は、ユーザーインターフェースへのJSONによるデータアクセスを提供することである。フレームワークとアプリケーション構造を提供するのが意図なので、例は基本的な機能しか実装していない。

モバイル開発の考慮事項

デスクトップブラウザ用のアプリケーション開発に取られる多くのアプローチは、モバイルブラウザーベースのアプリケーションにも適用できる。しかし、モバイルアプリケーションには、デスクトップブラウザがいつも要求するわけではない、いくつかの追加の考慮と挑戦が存在する。

スクリーン解像度を考慮する。ずっと小さなサイズであることで、アプリケーションとの最適なユーザーインタラクションのために異なるユーザーインターフェースが必要になる。HTML5が jQuery MobileのようなモバイルUIウィジットライブラリと一体になることでJavaScriptを使ってモバイル特有のユーザーインターフェースを作るクロスデバイスな手段を提供できる。下のスクリーンショットは、jQuery Mobile HTML5 のリストビューである。 
 

このモバイルUIは、HTML5のロール識別子とCSSを使ってレンダリングされる。以下はリストビュー用のHTMLタグの抜粋である。データ-ロール属性に注目して欲しい。このロールは、モバイルデバイスフレンドリーなユーザーインターフェースをレンダリングするのに、 jQuery Mobileによって使われる。

           

接続性は、もう一つの大きな考慮事項である。今日、3G ネットワークやWIFIが広く使用されているが、いつも接続性を想定できるわけではない。幸運にも、HTML5には、キャッシュ機能があるので、サイトリソースをローカルに「キャッシュ」でき、非接続モードで動く。キャッシングは、下に示すようにルートレベルのHTML要素に以下のものを追加することで、動作する。

<!DOCTYPE HTML>
        <html manifest="cache.manifest">
                  <body>
                  ...
                  </body>
        </html>

マニフェストファイルはテキストファイルで、キャッシュをバイパスできるリソースやリソースが無い時に表示すべきものをコントロールする他のディレクティブと一緒にキャッシュされるリソースを定義する。ファイルが変更された時やJavaScriptAPIによって、キャッシュの更新や通知もコントロールされる。キャッシュマニフェストファイルの例をいかに示す。

CACHE MANIFEST
# 2012-27-18:v1

# 明示的にキャッシュされたリソース
CACHE:
index.html
css/stylesheet.css
Images/logo.png
scripts/main.js

# ホワイトリストされたリソース、接続性を必要とし、キャッシュをバイパスする
NETWORK:
http://api.twitter.com


# もし*.HTMLがなければ、 offline.htmlが表示される
FALLBACK:
*.html /static.html

更に、HTML5はパフォーマンスと非接続動作のために、サーバーサイドデータをローカルにキャッシュできる機構を提供する。5メガのキー/値用のローカルストレージ機構が利用でき、文字列や文字列化されたJSONオブジェクトを保存できる。ローカルストレージは、 localStorageオブジェクトを使ってJavaScriptからアクセスできる。下の例は、StockオブジェクトのBackbone.Collection がどのようにJSON文字列としてローカルに保存され、呼び出すことができるかを示している。

var d = JSON.stringify(data);
localStorage.setItem('STOCKS', d);

var d = localStorage.getItem('STOCKS');
data = JSON.parse(d);

アプリケーションは、またユーザーに「非接続」を奥ゆかしく通知するように作ることもできる。中間のリモートデータアクセス要求は、 HTML5対応ブラウザーでキー/値のローカルストレージ標準にキューイングされる。接続性が回復した時に、ローカルに保存されたオブジェクトがサーバーにアップロードされる。

帯域幅は、また別の問題である。サーバーリクエストとペイロードサイズの最小化はAJAXサポートを使って、サポートでき、そしてJavasScript Object Notation (JSON) を使ってデータアクセスだけにサーバーを当てにする。JSONは、XMLすなわちSOAPベースのプロトコルのような従来の統合プロトコルよりも遥かに効率的で、簡潔である。

HTML5のアプリケーションアーキテクチャ

JavaScriptは汎用のアプリケーション開発言語であることを意図していなかった。その当初の意図は、ダイナミックHTMLがリモートサーバーにアクセスしなくてもレンダリングされ、変更することができるようにすることで、ブラウザでのユーザーエクスペリエンスを向上させることだった。これは、体感できると本当のパフォーマンス向上を提供している。モバイルデバイスには、デスクトップ/ラップトップ常駐ブラウザが持つような処理する馬力も帯域幅のあるアクセス能力も、無い。そこでリッチなユーザーインターフェースを実現するには、クライアント側にJavaScript やHTML5要素でできるだけ実装して、サーバーとのやり取りを最小限にする。

これは、動的なHTML要素がサーバーでレンダリングされている現在のサーバー側のwebアプリケーション(JSP / ASP / PHP)からの 決別である。この新しい形態では、サーバー側の要素は、認証およびデータアクセス要求、およびユーザとのやり取りをサポートしており、ほとんどのアプリケーション・ロジックがクライアントのブラウザに存在する。このことは、下の図で見ることができる。

更に、弱い型づけの動的言語(クロージャーやコードブロックをデータタイプとして扱える能力が可能である)がプログラミング上の柔軟性を提供している。しかし、それは、保守不能のコードに繋がりが得る。従って、JavaScriptベースのアプリケーションには、厳密さが適用されなければならない。下記のリストは、実現の必要がある一般的なメカニズムの幾つかである。

  • ナビゲーション
  • リモートデータアクセス
  • 認証/認可
  • アプリケーションモデルから切り離されたビュー(MVCパターン)
  • モジュール化/パッケージ化
  • 依存性管理
  • ロギング/トレーシング
  • 例外処理

Javaの世界では、フレームワークは、階層化アプリケーションアーキテクチャをサポートするために存在してい る。同様に、JavaScriptの世界でも、階層アプリケーションアーキテクチャをサポートするためにフレームワークが利用できる。 保守性と安定性のために、以下のJavaScriptフレームワークはモジュール化、階層化、およびオブジェクト指向のJavaScriptアプリケーションアーキテクチャを強制する助けのために 使うことができる。

Backbone.js

Backboneによって、 JavaScriptアプリケーションにモデル、ビュー、コントローラー(MVC)を分離して、MVCパターンを適用できる。HTML5ユーザーインタフェースは、コントローラーとオブジェクトモデルの実装から分離される。更に、ユーザーインターフェースフィーチャ間の標準的なナビゲーション機構が提供されている。

Require.js

JavaScriptファイルとモジュールローダフレームワーク。このフレームワークによって、Javaスクリプトモジュール/関数で "必要である"というときに依存するJavaスクリプトが読み込まれ、検証されるようになる。フレームワークは、依存性情報を通信しており、JavaScriptモジュール/ライブラリが読み込まれていない場合、開発者にエラーをアサートする。

_Underscore.js

Underscore.jsは、関数型プログラミングメカニズムをオブジェクトの集合に適用できるにするユーティリティメソッドを提供するライブラリである。またHTMLをテンプレート化するフィーチャも提供している。

JQuery

HTML DOM要素にアクセスし、操作するために使われるライブラリ。

jQuery Mobile

HTML5のユーザーインターフェイスコンポーネントライブラリ。HTML5でレンダリングされるUIコントロールのスイートを提供する。ルックアンドフィールと同様に、イベント処理のためのメカニズムを提供する。

khsSherpa

リモートJavaオブジェクトがHTTP要求を介してアクセスすることを可能にするJavaアプリケーション・サーバー・フレームワーク。それは自動でJSONオブジェクトにJava型のマーシャリングと一緒にトークンベースの認証をサポートしている。オプション:JSONPクロスドメインのサポートが有効になっている。

JavaScriptのフォルダ構造

JavaScriptは、プログラミング要素を構造化する標準的な方法を提供していない、単なるテキストベースの.jsファイルである。他の言語は構造化するメカニズムを持っている、例えばJavaのpackageやC#の名前空間である。一つの大きなファイルにある全てのJavaScript関数やオブジェクトを定義しょうとするのは、保守するのが厄介である。特に、アプリケーションの大部分がJavaScriptで定義されている場合である。なので、rootフォルダー下のファイルシステムフォルダは、 JavaScriptソースコードを責任別に分割するのに役立つように定義することができる。

フォルダーには、アプリケーションのMVC JavaScript要素が入っている。サンプル・アプリケーションの例では、フォルダ構造は以下の通りだ。これらのフォルダは、webサーバー/アプリケーションサーバーのドキュメントルートに配置されていると仮定する。

モジュール化のサポート

JavaScriptには、ソースコード要素を分割する組込みのメカニズムは無い。他の言語にはこのメカニズムが備わっている。再び例えば、JavaのpackageやC#の名前空間。しかし、アプリケーションは、依存モジュールを持ち込むためにディレクティブをインポートするか、含むことができる。これによって、アプリケーションとフレームワークは、コードをモジュール化して、保守性と再利用性を改善できる。

Require.js フレームワークは、効率的にJavaScriptファイルを分割して、モジュールとして扱うメカニズムを提供し、依存モジュールを定義し、インポートし、アクセスできる機能がある。

Requireフレームワークは、依存性の定義とロードを実現するのに、Asynchronous Module Definition (AMD非同期モジュール定義) フレームワークを使っている。モジュールをロードする require/AMD関数を以下に示す。

define([modules], factory function);

各モジュールは、JavaScriptオブジェクトを定義している個々のJavaScriptファイルだ。呼び出されると、モジュールがロードされ、オブジェクトのインスタンスが作成され、開発者が使用するファクトリ関数に渡される。以下の例では、require define()関数のロード・ユーティリティー依存関係を使っているJavaScriptモジュールを示す。

define(["util"], function (util) {
          return {
          date: function(){
                      var date = new Date();
          return util.format(date);
            }
      };
});

Require フレームワークは、ファイルの読み込みを最小限に抑え、パフォーマンスを向上させるために、最適化機能を備えている。

Backbone MVC

このフレームワークによって、人気のあるMVCデザインパターンがJavaScriptを使用して実装することができる。典型的なwebアプリケーションは、JSP / ASPまたはある種のHTMLテンプレートエンジンのような動的なHTML生成技術を使用して、サーバ側の汎用言語でこのパターンを実装している。フレームワークは、ユーザの入力を処理し、動的なHTMLメカニズムへのアプリケーションのオブジェクトモデルを適用するためのコンポーネントや抽象化を提供しる。Backbone フレームワークは、サーバー上でHTMLタグを生成するのではなく、JavaScriptでこれらのメカニズムを適用する方法を提供する。

HTML テンプレート

Backbone ビューは、HTML5の roleが適用されている、単なる静的なHTMLファイルである。Backbone はテンプレートメカニズムを提供しているので、ビューがビュー/コントローラによってレンダリングされる時に、モデルアトリビュートは、HTMLに適用できる。アプリケーション例では、JQuery Mobile のリストビューを定義しているが、リストビューはHTML5のroleアトリビュートを使って定義されている。 stock-list.html のHTML5ビューを以下に示す。

<div id="stockListContainer" data-role='content'>
          <ul data-role="listview" id='tcStockList' data-inset="true" data-filter="true"></ul>
</div>

リストビュー中の株式商品は、stock-list-item.htmlに定義されている。それは、Backboneテンプレートメカニズムを株式モデルJSONオブジェクトの詳細表示に適用する。テンプレート要素を持つHTMLを以下に示す。

<a href='#<%=ticker%>'>
          <h4><%= ticker %></h4>
          <p><%= name %></p>
          <p>Price: <%= price %></p>
</a>

上記のテンプレート式は、 JSP/ASPページに似ていることに気づくだろう。それらは、モデルのJSONオブジェクトからの特性値で置き換える場所に印を付けるために使われる。HTMLテンプレートは、 templateフォルダーにある。

ビュー/コントローラー

HTMLビューは、Backboneコントローラーの実装にナビゲートすることでレンダリングされる。コントローラーは、JavaScriptオブジェクトをHTMLビューにバインドし、イベントの定義と処理と共に、フレームワークにビューをレンダリングするように言う。 Backbone用語では、ビューはコントローラーであり、 Backboneビューの作成は、フレームワークが提供するBackone.View オブジェクトを拡張することによって実現される。

のビューコントローラーの部分的な例が以下であり、最初必要な JavaScript .jsファイルをrequire.js フレームワークを使ってロードする。それはBackboneビューコントローラー関数を返すdefine([modules,...], controller()) JavaScript関数を呼び出す。いかにこの関数がBackbone.View オブジェクトを拡張しているか注目して欲しい。 Requireフレームワークの Define関数の素晴らしいことは、それがビューコントローラーの実装が必要な依存しているモジュールをロードすることである。いかにモデルとHTMLテンプレートモジュールもビュー/コントローラーモジュールオブジェクトに提供されているかも注意して欲しい。

define([
                'jquery',
                'backbone',
                'underscore',
                'model/stockListCollection',
                'view/stockListView',
                'text!template/stock-list.html'],
                function($, Backbone, _, StockListCollection, StockListView, stockListTemplate) {var list = {};
                            return Backbone.View.extend({
                                      id : 'stock-list-page',


ビュー/コントローラーインスタンスが生成される時、initialize: function が呼ばれ、イベントを定義し、コントローラーモデルを初期化する方法を提供する。モデルは、個々のオブジェクトかオブジェクトのコレクションの場合もある。

stockListPage.js のビュー/コントローラーの initialize functionの例では、 StockListCollectionオブジェクトが生成されることに気づくだろう。コレクションもBackboneが提供するオブジェクトで、ビュー用のJavaScriptオブジェクトモデルの「コレクション」を管理する方法を提供する。このコントローラーが呼び出されると、initialize()メソッドが実行される。インスタンスが生成される時、それは Backboneイベントハンドラーをボタンに適用するのに jQueryセレクターを使う。 initialize functionのコード片を以下に示す。

var list = {};
return Backbone.View.extend({
          id : 'stock-list-page',
          initialize : function() {
                    this.list = new StockListCollection();

                    $("#about").on("click", function(e){
                              navigate(e);
                              e.preventDefault();
          e.stopPropagation();
                              return false;
                    });


                    $("#add").on("click", function(e){
                              navigate(e);
                              e.preventDefault();
          e.stopPropagation();

                              return false;
                    });


          },

イベントは、ビュー/コントローラーメソッドと関連付けられているが、それはイベントと jQueryセレクターをメソッド名と関連付けることで実現される。以下の例が示しているのは、アプリケーション例と株のリストページ上のaddボタン用のイベントとハンドリングメソッドである。navigationコマンドに注意して欲しい。それは、次のセクションで議論される。

events: {
 "click #about" : "about",
 "click #add" : "add",
},
about : function(e) {

window.stock.routers.workspaceRouter.navigate("#about",true);
          return false;
},

add : function(e) {
                    window.stock.routers.workspaceRouter.navigate("#add",true);
          return false;
},

View/Controllers HTMLテンプレートがレンダリングされるのは、render()メソッドがインスタンスに送られる時である。 stockListPage.jsの render functionを下に示す。それがどのようにテンプレートをコンパイルし、次にコントローラーのelアトリビュートに適用されるHTMLテンプレートを表示するかがわかるだろう。 this.elアトリビュートは、HTMLが挿入される時、DOM中のコントローラーのロケーションである。次に、どのようにまた別のビュー/コントローラーがインスタンス化され、レンダリングされるかに注目して欲しい。 StockListViewコントローラーは、株の JQueryMobileのリストビュー(listview)をレンダリングする。

          render : function(eventName) {
                    var compiled_template = _.template(stockListTemplate);
                    var $el = $(this.el);
                    $el.html(compiled_template());
                    this.listView = new StockListView({
                              el : $('ul', this.el),
                              collection : this.list
                    });
                    this.listView.render();
                    return this;
                    },
          });
});

ナビゲーション

コントローラのビュー間をナビゲートするのは、Backbone が提供するまた別のメカニズムである。Backbone はこのことを "ルーティング"と呼んでおり、ナビゲーションルートを定義するように拡張することができるBackbone.Routerオブジェクトが用意されている。例アプリケーションのルータを以下に示す:

define(['jquery', 'backbone', 'jquerymobile' ], function($, Backbone) {
          var transition = $.mobile.defaultPageTransition;
          var WorkspaceRouter = Backbone.Router.extend({
                    // bookmarkMode : false,
                    id : 'workspaceRouter',
                    routes : {
                              "index" : "stockList",
                              "stockDetail" : "stockDetail"
                    },
                    initialize : function() {
                              $('.back').on('click', function(event) {
                                        window.history.back();
                                        return false;
                              });
                              this.firstPage = true;
                    },
                    defaultRoute: function() {
                              console.log('default route');
                              this.runScript("script","stockList");
          },
          stockDetail: function() {
                    require(['view/stockDetailView'], function (ThisView) {
                                        var page = new ThisView();
                                        $(page.el).attr({
                                                  'data-role' : 'page',
                                                  'data-add-back-btn' : "false"
                                        });

                                        page.render();

                                        $(page.el).prependTo($('body'));

                                        $.mobile.changePage($(page.el), {
                                                  transition : 'slide'
                                        });

                    });
          },

          stockList : function() {

                              require(['view/stockListPage'], function (ThisView) {
                                        var page = new ThisView();

                                        $(page.el).attr({
                                                  'data-role' : 'page',
                                                  'data-add-back-btn' : "false"
                                        });

                                        page.render();

                                        $(page.el).prependTo($('body'));

                                        $.mobile.changePage($(page.el), {
                                                  transition : 'flip'
                                        });
                     });
                    },

          });
          return new WorkspaceRouter();
});

Require Define 関数が jQueryのインスタンス、BackboneやjQuery Mobile インスタンスをオーバーライドされたrouter 関数/メソッドに提供するために使われている。 Routerインスタンスが生成される時に、routeはIDと"route"がナビゲートされる時に実行される関数名を使って初期化される。上記の例では、2つのroute: #index #stockDetailがある。関数はこれらのルート用に定義されているのに注意。

ルーターオブジェクトは、以下の式で定義されたビュー/コントローラにナビゲートするために呼び出すことができる。

.navigate("#index");

ルーティング関数は、Backbone.View のインスタンスを生成して、レンダリング関数を呼び出す。以下のコード片は、株リストを jQuery Mobileのリストビューにレンダリングする拡張されたBackBone.Router関数の例である。以下のソースを見ると、どのように Requireフレームワークが view/stockListPageのBackboneビュー コントローラのインスタンスを作成し、それから JQueryを使って、ページアトリビュートを飾り、それをレンダリングする、のかがわかる。

// ルーターナビゲーション関数
stockList : function() {
                    require(['view/stockListPage'], function (ThisView) {
                              var page = new ThisView();
                              $(page.el).attr({
                                        'data-role' : 'page',
                                        'data-add-back-btn' : "false"
                              });
                              page.render();

                              $(page.el).prependTo($('body'));

                              $.mobile.changePage($(page.el), {
                                        transition : 'flip'
                              });
          });
        },

コレクション/モデル

Backboneは、Backbone.Modelオブジェクトのリストを管理するコレクションオブジェクトを提供する。 View/Controllerオブジェクトは、リストあるいは1つのJavaScriptオブジェクトを参照するアトリビュートを持っている。ビュー/コントローラに表示される StockListItem モデルオブジェクトのためのBackbone.Collectionオブジェクトを下に示す。

define(['jquery', 'backbone', 'underscore', 'model/stockItemModel'],
function($, Backbone, _, StockListItem) {
          return Backbone.Collection.extend({
                    model : StockListItem,
                    url : 'http://localhost:8080/khs-sherpa-jquery/sherpa?endpoint=StockService&action=quotes&callback=?',
                    initialize : function() {
                              $.mobile.showPageLoadingMsg();
                              console.log('findScripts url:' + this.url);
                              var data = this.localGet();
                              if (data == null) {
                                        this.loadStocks();
                              } else {
                                        console.log('local data present..');
                                        this.reset(data);
                              }
                    },
                    loadStocks : function() {
                              var self = this;
                              $.getJSON(this.url, {
                                        }).success(function(data, textStatus, xhr) {
                                                  console.log('script list get json success');
                                                  console.log(JSON.stringify(data.scripts));
                                                  self.reset(data);
                                                  self.localSave(data);
                                        }).error(function(data, textStatus, xhr) {
                                                  console.log('error');
                                                  console.log("data - " + JSON.stringify(data));
                                                  console.log("textStatus - " + textStatus);
                                                  console.log("xhr - " + JSON.stringify(xhr));
                                        }).complete(function() {
                                                  console.log('json request complete');
                                                  $.mobile.hidePageLoadingMsg();
                                        });
                    },
                    localSave : function(data) {
                              var d = JSON.stringify(data);
                              localStorage.setItem('STOCKS', d);
                    },
                    localGet : function() {
                              var d = localStorage.getItem('STOCKS');
                    data = JSON.parse(d);
                    return data;
          }
          });
});

コレクションオブジェクトが初期化される時、(アプリケーション例では、ビュー/コントローラがインスタンスを作成する時にこれが起きる)指定されたURLアトリビュートが 呼び出されjQuery AJAXメカニズムを使って、サーバー側のJSONPエンドポイントを呼び出す。エンドポイントは、JSON株オブジェクトを返すが、これは自動的にコレクションのstockListItemモデルにマップされる。 StockItemModel用の Backbone.Model定義は、以下に示すようになる。

define(['jquery',
                         'backbone',
                         'underscore'],
                         function($, Backbone, _) {
                                        return Backbone.Model.extend({
                                                  initialize : function() {

                                                  }

                                        });
});

強く型付けされた言語に馴染んでいる読者には、JSON形式の文字列をJavaScriptモデルオブジェクトに変換するJavaScriptの機能は、魔法のように思えるだろう。

Backbone.Modelには、保存に役立ったり、サーバーと同期を取る幾つものメソッドが備わっている。同様に、 Backbone.Collectionにも、サーバーと同期を取り、保存するためのメッソドの他に、関数型プログラミングタイプの操作を実行するためのメソッドがある。これらの能力を ここで確認できる。

ローカルストレージ

この例のStockListCollection の拡張された Backbone.Collection に追加された他のメソッドは、HTML5ローカルストレージ機構にオブジェクトを保存したり、復元する機能を提供する。これらのコレクションにlocalSave() localGet() が定義されている。株オブジェクトをサーバーから一度入手すれば、HTML5アプリケーションは、接続がなくても操作できる。この例は、キー/値ローカルセッションストレージ機構を使っている。HTML5はまた、 webSQLとして参照できるローカルなリレーショナルストレージ機構を提供する。しかし、この仕様に向けた開発は停滞しており、それは完全にサポートされていない。なので、その存在に依存するのは危険かもしれない。 キー/値セッションストレージは、充分サポートされている。 webSQL仕様に関するより詳しい情報は、ここにある

アプリケーションのブートストラップ/起動

標準のIndex.html が物事を起動するのは、ロードされたスタイルシートが以下のタグと一緒に定義された時である。

これがMain.js 関数を呼び出し、この関数がサポートしているJavaScriptライブラリを設定し、ロードする。 Requireフレームワークは、JavaScriptライブラリを簡単な名前やベースのURLロケーションパスに関連付けられる素晴らしい機構を持っている。libフォルダーは、docルートから外れているので、ベースURLパスは不要である。以下のコード片に例を示す。

require.config({
                    paths : {
                              'backbone' : 'libs/AMDbackbone-0.5.3',
                              'underscore' : 'libs/underscore-1.2.2',
                              'text' : 'libs/require/text',
                              'jquery' : 'libs/jquery-1.7.2',
                              'jquerymobile' : 'libs/jquery.mobile-1.1.0-rc.2'
                    },
                    baseUrl : ''
          });

このスタートアップ関数はまた、 jQuery Mobileプロパティを構成するのに、 require関数を使い、App.js スクリプトをロードし、stock-list-item.htmlを表示するのに#index ルートにナビゲートする。

App.jsを以下に示す。それは、ワークスペースルーター(WorkspaceRouter)インスタンスを初期化し、 backboneを起動し、それから#index ページにナビゲートする。ソースを以下に示す。

define(['backbone', 'router/workspaceRouter'], function(Backbone, WorkspaceRouter) {

          "use strict";

          $(function(){
                    window.tc = {
                              routers : {
                                        workspaceRouter : WorkspaceRouter
                              },
                              views : {},
                              models : {},
                              ticker: null
                    };

                    var started = Backbone.history.start({pushState:false, root:'/HTML5BackboneJQMRequireJS/'});
                    window.tc.routers.workspaceRouter.navigate("#index", {trigger:true});
          });
});

サーバー側のJSONエンドポイント

khsSherpa JSONのフレームワークを使用するように構成されたアプリケーション・サーバーは、リストと個々のストックオブジェクトを生成、読み込み、アップデート、消去するメソッドを提供するエンドポイントにURLを提供する。フレームワークは、HTTPリクエストパラメータをJavaエンドポイントのメソッドコールにマーシャリングし、JavaオブジェクトをJSON文字列にシリアライズしたり、逆にデシリアライズする。

この例のプロジェクトは、 JEE WARコンポーネントとして定義され、デプロイされることを意図している。このWARは、クライアントブラウザーに最初配置され、常駐する静的な HTML/JavaScriptと HTML5インターフェースを動かすSherpa JSON Javaアプリケーション・サーバーエンドポイントの両方を持っている。

JSON形式で株価JSONオブジェクトを提供するJavaサーバーエンドポイントの定義を示す。エンドポイントは、 HTTP URL getを使って呼びだされる。

この例のアプリケーションは、株オブジェクトのコレクションを取得するのにエンドポイントが必要なだけだ。しかしもっと現実的なアプリケーションは、CRUD操作をサポートするのに認証ともっとエンドポイントが必要になるだろう。このフレームワークは、これらの要求をサポートしている。もっとフィーチャを記述したものが欲しいなら、Githubにあるフレームワークを確認して欲しい

結論

これ例は機能的には単純化されているが、目的はブラウザ常駐のアプリケーション用のMVCアプリケーションを紹介することだった。アプリケーションインタフェースの動的HTMLをレンダリングするのに必要なアプリケーション・サーバーの必要性を排除することが、この論文で提示されたアプリケーションアーキテクチャの主要なフィーチャである。JavaScriptは自然な汎用目的のプログラミング言語ではないが、モバイルデバイスの爆発、HTML5の大々的な採用、ブラウザプラグイン技術への抵抗と非サポートによって、HTML5とJavaScriptがモバイルデバイスにリッチなブラウザベースのアプリケーションを提供する実現可能な方法になる。

例題アプリケーションの完全なソースは、GitHubにある。

著者について

David Pitt氏は、Keyhole Softwareのシニア Solutions Architectで Managing Partnerである。25年近いIT経験があり、最後の15年間は、企業のIT部門がオブジェクト技術を導入する助けをしてきた。1999年以来、Java (JEE) と .NET (C#)ベースの技術を使ってソフトウェア開発している、開発チームを率いてきており、そして指導もしてきた。彼は多数の技術記事の著者であり、彼のアーキテクチャのデザインパターンのいくつかを文書化した、人気のIBM WebSphereの本の共著者でもある。

 

この記事に星をつける

おすすめ度
スタイル

BT