HTML 5 で作る
オフラインWebアプリケーション

                      2012/05/28
         第5.5回 GTUG Girls Meetup
   Toru Yoshikawa ( @yoshikawa_t )
Who?
吉川 徹/Toru Yoshikawa
  html5j.org/HTML5とか勉強会スタッフ

  Google API Expert ( Chrome )/Chrome API Developers
  JP

  Sublime Text 2 Japan Users Group

  allWebクリエイター塾/jQuery Mobile担当講師

  Twitter: @yoshikawa_t

  Blog: http://d.hatena.ne.jp/pikotea/
Agenda
オフラインWebアプリケーションとは?

オフラインWebアプリケーションの作り方

オフラインWebアプリケーションの関連する仕様

  1. ファイルのキャッシュ(Application Cache)

  2. データの保存(Web Storage)

  3. データベース(Indexed Database/Web SQL Database)

  4. データの同期、他(Online/Offline events, Network
  Information API, Shared Worker)

  5. ファイルの保存(File APIs)

まとめ
オフラインWebアプリケーションとは?
オフラインWebアプリケーションの特徴

 オフラインで動作させることができる

  地下鉄などネットワークが使えない環境で
  も利用できる

  サーバーが落ちていてもサイトを表示する
  ことができる

 必要なリソースをキャッシュするため、高速
 に動作する
Demo: Angry Birds




    http://chrome.angrybirds.com/
Demo: Financial Times




        http://app.ft.com/
オフラインWebアプリケーションの作り方


1.必要なファイルをキャッシュする

2.ユーザーデータ・設定をローカルに保存する

3.アプリケーションデータをローカルに保存
 する

4.必要があれば適時、データの同期を行う

5.ファイルをローカルに保存する
従来のWebアプリケーションのアーキテクチャ


             Webサーバー   DB




HTML/CSS/                   アプリケーションデータ
JavaScript



             ブラウザ
オフラインWebアプリケーションのアーキテクチャ
              (その1: シンプルな構成)


              Webサーバー



             キャッシュ


HTML/CSS/
JavaScript



              ブラウザ

        アプリケーションデータ     DB
オフラインWebアプリケーションのアーキテクチャ
             (その2: データの同期がある)


              Webサーバー        DB


             キャッシュ


HTML/CSS/                          データの同期
JavaScript



              ブラウザ           バックグラウンド

        アプリケーションデータ     DB
オフラインWebアプリケーションに関連する仕様

 必要なファイルをキャッシュする

   Application Cache

 ユーザーデータ・設定、アプリケーションデータをローカルに保存

   Web Storage

   Indexed Database/Web SQL Database

 必要があれば適時、データの同期を行う、他

   Online/Offline events

   Network Information API

   Web Workers (Shared Worker)

 ファイルをローカルに保存

   File APIs (File API, File API: Directories and System)
オフラインWebアプリケーションのアーキテクチャ



              Webサーバー               DB

                                               XHR2
                                            WebSockets
             AppCache

                                  Online/Offline events
HTML/CSS/                        Network Information API
JavaScript


                                  Shared Worker
               ブラウザ
       アプリケーションデータ      Web Storage
                        IndexedDB/WebSQL
                        File APIs
サンプル: オフラインTODOアプリ

http://dl.dropbox.com/u/18090951/gg5_5_offlineapp_todo.zip
1. 必要なファイルをキャッシュする
   Application Cache
Application Cache とは?

 ファイルをキャッシュする(静的ファイル)

 html/css/javascript/画像などをそのまま
 キャッシュすることができる

 既存のサイトにほとんど手を加えなくてもそのま
 ま適用できる

 既に多くのモバイルデバイスでサポートしている
Application Cache の利用方法

1.マニフェストファイルを作成する

2.<html>要素のmanifest属性でマニフェスト
 ファイルを記述して読み込む

3.(サーバー設定でマニフェストファイルのMIME
 Typeをtext/cache-manifestに設定する)
1. マニフェストファイルを作成する
site.appcache

CACHE MANIFEST
#last update: 2012/05/28

CACHE:
menu.html
css/reset.css
js/javascript.js

FALLBACK:
#index.html index_offline.html

NETWORK:
*
2. <html>要素のmanifest属性でマニフェスト
              ファイルを記述して読み込む
index.html

<!DOCTYPE html>
<html manifest="site.appcache">
...
</html>
3. サーバー設定でマニフェストファイルのMIME
     Typeをtext/cache-manifestに設定する
 ※ 将来的には、不要になります

Example: Apacheの.htaccessでの設定例
.htaccess

AddType text/cache-manifest .appcache


Example: JEEでの設定例
web.xml

<mime-mapping>
  <extension>manifest</extension>
  <mime-type>text/cache-manifest</mime-type>
</mime-mapping>
Application Cacheの注意点

 マニフェストファイルを読み込むhtmlファイルは自動的にキャッ
 シュされる

 ひとつでもエラーがあると全体がキャッシュされない(構文エラー
 や404など)

 ファイルの更新と同時に、マニフェストファイルの更新を忘れずに

 XHRにはキャッシュが適用されない

 メディアファイル(動画や音声)はまだ非サポート(※キャッシュさ
 れるがオフラインで再生できない)

 保存できる容量は20MB∼30MB程度(Chromeはディスクの10%)
Application Cacheの参考情報

 マニフェストファイルの生成ツール(manifestR)

 バリデーター(Cache Manifest Validator)

 A BEGINNER'S GUIDE TO USING THE
 APPLICATION CACHE - HTML5 Rocks

 Application Cacheの削除(Chromeの場合)
 chrome://appcache-internals
2. ユーザーデータ・設定をローカルに保存する
        Web Storage
Web Storage とは?
文字列データをブラウザに保存することができる

連想配列のようにキーと値をセットにして保存する
(KVS型)

ブラウザを閉じると消えるsessionStorageと、ブラ
ウザを閉じても保存されるlocalStorageがある

非常にシンプルなAPI

IE8から使える!
Web Storage の利用方法
データの保存

// fooというキーでbarという値を保存する
// 利用方法は3つの書き方があるが、いずれも同じ結果になる
localStorage.setItem("foo", "bar");
localStorage.foo = "bar";
localStorage[foo] = "bar";


データの取得

// fooというキーで値を取得する
localStorage.getItem("foo");
localStorage.foo;
localStorage[foo];
Web Storage の利用方法
データの削除

// fooというキーのデータを削除する
localStorage.removeItem("foo");

// すべて削除する
localStorage.clear();


データの一覧
//保存されている値をすべて表示する
for ( var i = 0, len = localStorage.length; i < len; i++ ) {
  console.log( localStorage.getItem(localStorage.key(i)) );
}
Web Storage の利用方法
JavaScriptオブジェクトを扱う

// JavaScriptオブジェクトをJSON化して保存する
var data = {
	 foo: bar
};
localStorage.setItem('data', JSON.stringify(data));

// JavaScriptオブジェクトに戻して取得する
var data = JSON.parse( localStorage.getItem('data') );
Web Storageの注意点

オリジン(プロトコル、ドメイン、ポート)ごと
にデータが保存される( Same Origin
Policy)

保存できる容量は、5MB程度

個人情報やパスワードのような機微なデータは保
存しない方が良い
Same Origin Policy
各APIのスコープをオリジンごとに制限する
HTML5共通の仕様

•   オリジンは次の3つで構成される

    •   スキーマ

    •   ドメイン

    •   ポート

http://example.com:80/
3. アプリケーションデータをローカルに保存する
 Indexed Database/Web SQL Database
Indexed Database とは?

 JavaScriptオブジェクトを保存できる

 インデックスによる検索が可能(非SQL)

 トランザクションによる複数のデータ操作が可能

 APIが少し難解で扱いづらい

 Chrome、Firefoxが対応(IEは10から対応)
Web SQL Database とは?

 RDBMS

 SQLでデータを操作することができる

 仕様策定が停止されている

 Chrome、Safari、Operaが対応

 モバイルはAndroid、Safariが対応
Indexed Database の利用方法
データベースの作成
// データベースの作成
var request = indexedDB.open("dbName", 1);

// データベースのスキーマ作成
request.onupgradeneeded = function(event) {
  var db = event.target.result;

  // オブジェクトストアの作成
  var objectStore = db.createObjectStore("objectStoreName", { keyPath: "id" });
  // インデックスの作成
  objectStore.createIndex("indexName", "name", { unique: false });
  // イニシャルデータの保存
  var data = [
     { id: 1, name: "a", email: "a@example.com", tel: "0123" },
      { id: 2, name: "b", email: "b@example.com", tel: "4567" }
   ];
   for (i in data) {
      objectStore.add(data[i]);
   }
};
Indexed Database の利用方法
データベースのオープンとデータの取得
// データベースのオープン
var openRequest = indexedDB.open("dbName");

openRequest.onsuccess = function(event) {
  var db = event.target.result;

     var transaction = db.transaction(["objectStoreName"]);
     var objectStore = transaction.objectStore("objectStoreName");
     var request = objectStore.get(1);
     request.onerror = function(evt) {
       // エラー
     };
     request.onsuccess = function(evt) {
        // console.log( request.result.name );
     };
};
Indexed Database の利用方法
カーソルを利用したデータの取得(イテレート)

var objectStore =
db.transaction("objectStoreName").objectStore("objectStoreName");

objectStore.openCursor().onsuccess = function(event) {
   var cursor = event.target.result;
   if (cursor) {
     // console.log( cursor.value.name);
     cursor.continue();
   }
};



インデックスを検索
var index = objectStore.index("indexName");
index.get("a").onsuccess = function(event) {
   // console.log(event.target.result.id);
};
Indexed Database の利用方法
データの追加
var transaction = db.transaction(["objectStoreName"], IDBTransaction.READ_WRITE);

var objectStore = transaction.objectStore("objectStoreName");
var request = objectStore.add({
	 //...
});
request.onsuccess = function(event) {
  // データ追加成功
}
Indexed Databaseの注意点

 JavaScriptオブジェクト内のfunctionなどは保存できな
 い(Structure Clone Algorithm)

 オブジェクトストアやインデックスの作成は、データベース
 オープン時の特殊なトランザクション中にしか変更できない
 (Chromeでは、setVersionを使う)

 必ずトランザクションを利用してデータの取得、更新を行う

 データをソートするには、ソート用のインデックスを作成す
 る
Structured Clone Algorithm
JavaScriptデータをコピーする際にオブジェクトか
ら関数や循環参照を取り除いてコピーするアルゴ
リズム。Indexed Databaseのデータの保存やWeb
Workersでのメッセージの交換に利用されている
// コピー前
var data = {
  for: "bar",
  test : function(){
	    //...
  }
}
// コピー後
/* data = */ {
  for: "bar"
}
Indexed Databaseの参考情報

 A SIMPLE TODO LIST USING HTML5
 INDEXEDDB -HTML5 Rocks

 Using IndexedDB - MDN

 jdb.js
4. 必要があれば適時、データの同期を行う
    Online/Offline events
   Network Information API
        Shared Worker
Online/Offline eventsとは?


 Demo ( http://html5-
 demos.appspot.com/static/
 navigator.onLine.html )

 オンライン/オフラインの状態を取得できる

 オンラインになったときに同期を開始するなどの
 処理を行うことができる
Online/Offline events の利用方法
オンライン/オフライン状態の取得
if ( navigator.onLine ) {
  console.log('ONLINE');
} else {
  console.log('OFFLINE');
}



オンラインイベント
window.addEventListener('online', function(e) {
  // 同期の開始
}, false);
Online/Offline eventsの注意点


  接続しているネットワークしか見ていないので、
  オンラインになったからといってインターネット
  に繋がっているとは限らない
Network Information APIとは?

  接続しているネットワークの速度、課金の有無な
  どを取得できる

  ネットワークが遅い場合や従量課金で接続してい
  る場合などは、同期を自動で行わないなど処理を
  分けることができる

  Android 2.2+、Firefoxのみで利用可能
Online/Offline events の利用方法
ネットワークの速度を取得する(MB/s)
if ( navigator.connection.bandwidth < 2 ) {
	 // 2MB/s以下の場合
} else {
	 // ブロードバンド接続の場合
}



課金の有無を取得する
if ( navigator.connection.metered == false ) {
  // データ同期処理
}
Shared Workerとは?

バックグラウンドでJavaScriptを動作させるこ
とのできるWeb Workersの仕様のひとつ

複数のウィンドウ(タブ)で共通のひとつのバッ
クグラウンド処理を利用できる

データの同期をバックグラウンドで行う際に便利
Shared Worker の利用方法
ワーカーの作成とメッセージの送受信
var worker = new SharedWorker('worker.js');
worker.addEventListener('message', function(e) {
  console.log('メッセージ受信: ', e.data);
}, false);

worker.postMessage('メッセージ送信');


worker.js
// 受け取ったメッセージをそのまま返信
self.addEventListener('message', function(e) {
  self.postMessage(e.data);
}, false);
Shared Worker の参考情報

 THE BASICS OF WEB WORKERS - HTML5
 Rocks
5. ファイルの保存
 File APIs
File APIs とは?
大きな仕様は、File APIとFile API: Directories and
Systems (File System API)の2つ

File APIでは、ドラッグ&ドロップされたファイルを読み取るFile
Readerなどが定義されている

File System APIでは、Webアプリケーションで利用可能なファイル
システム領域を作成できる

バイナリファイルをそのまま保存しておきたい場合などに利用する

Demo ( http://www.htmlfivewow.com/demos/terminal/
terminal.html )

現状は、Chromeのみでの実装
File System API の利用方法
選択したファイルをコピーして保存する
<input type="file" id="myfile" multiple />



document.querySelector('#myfile').onchange = function(e) {
  var files = this.files;
  window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
    for (var i = 0, file; file = files[i]; ++i) {

       (function(f) {
         fs.root.getFile(file.name, {create: true, exclusive: true},
function(fileEntry) {
           fileEntry.createWriter(function(fileWriter) {
             fileWriter.write(f);
           }, errorHandler);
         }, errorHandler);
       })(file);
     }
   }, errorHandler);
};
File APIs の参考情報

READING FILES IN JAVASCRIPT USING THE
FILE APIS - HTML5 Rocks

EXPLORING THE FILESYSTEM APIS - HTML5
Rocks

ファイルのクォータを管理するQuota
Management APIも策定中
まとめ
まとめ
Application CacheやWeb Storageなどは、簡単
に利用できるので手軽に導入できる

反面、Indexed Databaseはまだまだ利用できる環
境も少なく、扱いづらいため普及と便利なライブラ
リが待ち望まれる

データの同期を行うWebアプリケーションの場合、
フェールセーフやコリジョンなどを考えるので難易度
が非常に高くなる。コストとの兼ね合いを
Thank you!!
 ( @yoshikawa_t )
Resources

HTML5のオフライン機能( http://gdd11-html5-
offline.googlecode.com/git/japanese.html )

HTML5 Rocks ( http://www.html5rocks.com/ja/ )

Mozilla Developer Network ( https://developer.mozilla.org/
ja/ )

When can i use... ( http://caniuse.com )

Mobile HTML5 ( http://mobilehtml5.org/ )

HTML5でオフラインWebアプリケーションを作ろう