Webアプリケーションを作成するための「オフライン優先」アプローチ

今年のフルフロンタル会議では、オフラインアプリケーションが一般的なトピックでした。 Paul Kinlanは、「未来のWebアプリケーションを構築する」というすばらしい講演を行いました。 明日、今日、昨日」(スライドはこちら )、彼はiOSとAndroid用の50の人気モバイルアプリケーションを使用したユーザーエクスペリエンスとWebサイトとアプリケーションのエクスペリエンスを比較しました。



言うまでもなく、ネイティブアプリケーションは、インターネット接続が利用できなかったときに、はるかに優れた側面から証明されました。 オフラインモードは非常に重要なことです。オフラインモードは、アプリケーションでの作業の最初から検討する必要があります。時間があるときに追加することを期待しないでください。 Rareloopの Webサイトで作業しているとき最初からオフラインモードを思い出しました。 FormAgentモバイルクライアントもともとオフラインで動作するように設計されていたため、ユーザーはインターネットがなくても作業を継続でき、接続が表示されたときに透過的に同期できます。 この記事では、このようなアプリケーションの開発に非常に役立つ原則と実践について説明します。



注意してください! アプリケーションリソースのキャッシュの問題は考慮していません。アプリキャッシュまたはハイブリッドソリューション( PhoneGapなど )を使用できますが、問題はありません[ 翻訳者から:Habréには、アプリケーションキャッシュAPIの機能に関する詳細な記事があります ]。 このガイドでは、実装に使用するメカニズムよりも、オフラインで動作するWebアプリケーションアーキテクチャの設計方法に重点を置いています。



基本原則



可能な限りサーバーからアプリケーションを解放します


歴史的に、Webページのほとんどの作業はサーバーに引き継がれていました。 データはデータベースに保存され、PHPやRubyなどのサーバー言語のコードの厚いレイヤーを介してアクセスされ、データはテンプレートを使用してHTMLで処理およびレンダリングされました。 最新のフレームワークのほとんどは、MVCアーキテクチャを使用してこれらのタスクを分離していますが、すべてのハードワークは依然としてサーバー上で実行されます。 情報の保存、処理、表示には、サーバーとの常時通信が必要です。



オフラインの最初のアプローチでは、MVCスタック全体をクライアント側に移動します。 サーバー側では、データベースにアクセスするための軽量のJSON APIのみがあります。 これにより、サーバーコードがはるかに小さく、シンプルになり、テストが容易になります。



ジェームス・ピアスはまた、これについてフル・フロンタル( スライド )でやや遊び心のある方法で話しました。

行に山かっこはありません-ちょうどカーリー!


要約:


  1. 最小限の機能を提供することにより、クライアントアプリケーションがサーバーなしで実行できることを確認します。 極端な場合、少なくともデータが利用できないことを示すメッセージ。
  2. JSONを使用します。




クライアント側でサーバーAPIのラッパーオブジェクトを作成する


ネストされたコールバックを使用したAJAX呼び出しでアプリケーションコードを汚染しないでください。 アプリケーション内のサーバーの機能を表すオブジェクトを作成します。 これにより、コードの分離が促進され、テストとデバッグが容易になり、まだ実装されていないサーバー機能の代わりに便利なスタブを使用できます。 このオブジェクト内ではAJAXを使用できますが、残りのアプリケーションの観点からは、サーバーとの通信方法を見る必要はありません。



要約:


  1. JSON APIを別のオブジェクトに抽象化します。
  2. AJAX呼び出しでアプリケーションコードを散らかさないでください。


データウェアハウスからデータの更新を解きます


サーバーAPIを抽象化するオブジェクトから直接データを要求し、すぐにそれを使用してテンプレートをレンダリングするように誘惑されるべきではありません。 APIオブジェクトとアプリケーションの他の部分との間のプロキシとして機能するデータオブジェクトをより適切に作成します。 このデータオブジェクトは、データ更新の要求を処理し、接続が切断されたときに状況を処理します-オフライン作業中に変更されたデータを同期します。



ユーザーがタイマーまたは「 online



」ブラウザイベントによって更新ボタンをクリックすると、データオブジェクトはサーバーに更新を問い合わせることができます。サーバーへの直接アクセスがないため、データキャッシュの管理が容易になります。



データオブジェクトは、永続ストレージ、ローカルストレージ、またはWebSQL / IndexedDBに状態をシリアル化して保存し、このデータを回復できる必要もあります。



要約:


  1. 別のデータオブジェクトを使用して、状態を保存および同期します。
  2. データを扱うすべての作業は、このプロキシオブジェクトを経由する必要があります。




簡単な例として、連絡先管理アプリケーションを取り上げます。 まず、生の連絡先データを取得できるサーバーAPIを作成します。 URI /contacts



がすべての連絡先エントリのリストを返すRESTful APIを作成したとします。 各レコードには、フィールドid



firstName



lastName



およびemail



ありemail







次に、このAPIのラッパーを作成します。



 var API = function() { }; API.prototype.getContacts = function(success, failure) { var win = function(data) { if(success) success(data); }; var fail = function() { if(failure) failure() }; $.ajax('http://myserver.com/contacts', { success: win, failure: fail }); };
      
      





ここで、アプリケーションとデータウェアハウス間のインターフェイスとなるデータオブジェクトが必要です。 次のようになります。



 var Data = function() { this.api = new API(); this.contacts = this.readFromStorage(); this.indexData(); }; Data.prototype.indexData = function() { //   (,  email) }; /* -- API -- */ Data.prototype.updateFromServer = function(callback) { var _this = this; var win = function(data) { _this.contacts = data; _this.indexData(); if(callback) callback(); }; var fail = function() { if(callback) callback(); }; this.api.getContacts(win, fail); }; /* --   -- */ Data.prototype.readFromStorage = function() { var c = JSON.parse(window.localStorage.getItem('appData')); //      return c || []; }; Data.prototype.writeToStorage = function() { window.localStorage.setItem('appData', JSON.stringify(this.contacts)); }; /* --  / -- */ Data.prototype.getContacts = function() { return this.contacts; }; //  ,    Data.prototype.getContactWithEmail = function(email) { //      ... return contact; };
      
      





これで、サーバーAPIから更新を要求できるデータオブジェクトができましたが、デフォルトではローカルに保存されたデータを返します。 アプリケーションの残りの部分では、次のコードを使用できます。



 var App = function() { this.data = new Data(); this.template = '...'; this.render(); this.setupListeners(); }; App.prototype.render = function() { //  this.template  this.data.getContacts()   HTML return html; } App.prototype.setupListeners = function() { var _this = this; //     $('button.refresh').on('click', function(event) { _this.refresh(); }); }; App.prototype.refresh = function () { _this.showLoadingSpinner(); _this.data.updateFromServer(function() { //     _this.render(); _this.hideLoadingSpinner(); }); }; App.prototype.showLoadingSpinner = function() { //   }; App.prototype.hideLoadingSpinner = function() { //   };
      
      





これは非常に単純な例です。実際のアプリケーションでは、おそらくデータオブジェクトをシングルトンとして実装する必要がありますが、オフラインで動作するようにコードを構成する方法を説明するにはこれで十分です。






All Articles