ネットワーク接続状況による処理の切り替え

ネットワーク接続状況による処理の切り替え

スマホでは、移動しているのてネットワークがオフラインになることもよくある

ネットにつながっているなら
ローカルストレージにキャッシュして

ネットがつながったらデータ送信
というようにするなら

if(navigator.onLine){
  //オンラインのときの処理
}else{ 
  //オフラインのときの処理
}

というようにする

Webアプリの更新

Webアプリの更新について

動的に内容が変更されるWebアプリで
アプリケーションキャッシュを使うと
最初に読み込んだ画面を、
ずっとキャッシュし続けるため
更新されなくなってしまう
このため、動的にHTMLが変更かれる箇所では
アプリケーションキャッシュは使わない

また、アプリケーションキャッシュとして読み込んだファイルは
ブラウザーから明示的に更新をチェックしないと
キャッシュが更新されないことがある

このため、更新チェックのJavascriptなどを使わないと
更新できないWebアプリになる

このため、
キャッシュファイルの更新と
アプリケーションの更新をする必要がある

まず、キャッシュファイルの更新を検知してWebアプリを更新する方法

アプリケーションキャッシュを示す
applicationCacheでは
キャッシュファイルが更新されると発生する
updatereadyイベントが使える

この
updatereadyイベントを使うことで
更新チェックと
新しいバージョンへのアップデートができる

if(applicationCache){
applicationCache.addEventListener("updateready",function(){
if(confirm("新しいバージョンが利用できます。アップデートしますか?")){

//キャッシュのアップデートと画面の再読込
applicationCache.swapCache();
location.load();

}

},true);

}

これだけでも更新チェックとアップデートができるけど
コンテンツを更新しても
updatereadyイベントが発生しないこともある

そのため念のために
update()
を、使うことで
明示的にキャッシュの更新と、リソース再読込ができるようにしておく

使い方は

applicationCache.update();

とする

これは、ボタンなどで使うことで
再読込ボタンにすることもできる

HTMLで

<button type="submit" id="update">更新</button>

Javascriptで

$(document).on("click","#update",function(e){
//キャッシュのアップデートと画面の再読込
applicationCache.update();
location.load();
});

注意点としては、Androidだと
アプリケーションキャッシュを使うことで
画面遷移ができなくなることがある

このため、Androidでは、Ajaxによる画面遷移を無効化しておく

if(navigator.userAgent.match(/Android/)){
$.mobile.ajaxEnabled = false;
}

match()は正規表現
マッチするものを調べるやり方

詳しくはドットインストールの正規表現を参考にするとわかりやすい

アプリケーションキャッシュについて

アプリケーションキャッシュについて

HTML5から追加された
アプリケーションキャッシュを使えば
ネットにつながっていなくてもWebアプリを動かすことができる

アプリケーションキャッシュでは
HTML
CSS
画像などのリソースをブラウザーでキャッシュして
サーバーへ読みに行かないようにする

これにより
サーバーへの負荷が減り
レスポンス向上、通信量削減もできる

ただし、デメリットがある
設定ができていないと
コンテンツのアップデートができなくなるので注意

アプリケーションキャッシュを使うには
appcacheファイルを作成する

このファイルの拡張子は
.appcache
になる

HTML5ファイル

一番最初の行へ

<DOCTYPE HTML>

としたり

シェルスクリプトファイルで
一番最初の行へ

#!/bin/bash

とするように

アプリケーションキャッシュでは

CACHE MANIFEST

と書く

そして、2行目に

#Version: 1.0

というように、バージョンをコメントアウトで書く

アプリケーションキャッシュファイルのコメントアウトは
Linuxの設定ファイルのように
#を付けることでできる
有効範囲は行末まで

そして、3行目からはキャッシュしたいファイルを記述していく

ファイルのパスは
キャッシュファイルからの相対パスでも
http:// の絶対パスでも構わない

#でコメントアウトができるので
ファイル概要があるとわかりやすくなる

ソースにすると

CACHE MANIFEST
#Version: 1.0

index.html
menu.html
#Javascript
js/jquery-1.7.1.min.js
js/jquery-mobile-1.1.0.min.js
#CSS
css/jquery-mobile-1.1.0.min.css

これで、アプリケーションキャッシュファイルができたので
後はHTMLファイルの
html要素へ
manifest=”” でアプリケーションキャッシュファイルを指定する

今回作成したのが
hello.appcacheなら

<! DOCTYPE html>
<html manifest="hello.appcache">

</html>

となる

これで、Webアプリの設定はできたので
次に、サーバー側の設定

サーバーソフトとしてApacheを使っている場合
デフォルトだと
.appcacheファイルは
text/plain形式になるので

正しく動作させるため
text/cache-manifestファイルになるように設定する

これは、 .htaccessファイルを作成して
キャッシュファイルと同じディレクトリに置く

.htaccessの内容は

addType text/cache-manifest .appcache

アプリケーションキャッシュを使うと
iOSやAndroidでは
まず、appcacheファイルを取得し
キャッシュの設定のあるファイルを
キャッシュから読み込んで表示する

appcacheファイルをWebサーバーから取得できない場合
キャッシュされたappcacheの情報に基づき
コンテンツをキャッシュから表示する

DOMキャッシュについて

DOMキャッシュについて

jQueryMobileは、DOMキャッシュ機能を持っている

これほ、一度表示した画面、つまりDOMをjQueryMobileの中にキャッシュして、キャッシュしたDOMを表示する機能

これは、メニュー画面など、
頻繁に表示されるページに利用する

DOMキャッシュで
すべての画面をキャッシュするには
jQueryMobileを初期化時に
$.mobile.page.prototype.options.domCache
をtrueにする

$(document).on("mobileinit",function(){
$.mobile.page.prototype.options.domCache = true;

});

これは、mobileinitイベントで定義する

次に、特定の画面のみキャッシュする方法

すべての画面をキャッシュするのはリソースの無駄なので行わない

キャッシュするのは
メニュー画面など
頻繁に再訪が発生するページのみにする

キャッシュ画面の指定は
画面の要素、つまり
data-role=”page”
に対して
data-dom-cache=”true”
を設定する

ソースにすると

<div data-role="page" data-dom-cache="true" id="menu">

</div>

なお、DOMキャッシュは、アプリケーションキャッシュを使うなら不要になる

次の画面を先読みするプリフェッチ機能

次の画面を先読みするプリフェッチ

ある画面から次の画面に移るときに
画面が変わるタイミングでデータ読み込みがあると
画面が表示されるまで時間がかかることがある
特に低速回線の場合は多発する

この対処としては、jQueryMobileで提供されているプリフェッチ機能を使えば
ユーザーに今の画面を表示している間に
次の画面のデータを事前に読み込んでおける

このプリフェッチ機能により
あらかじめ次の画面を読み込んでおくことで
スムーズに画面遷移ができる

これは、アンケートとかユーザー登録みたいな次に遷移するページが決まっているときに使う

プリフェッチ機能を使うには
リンクする a要素へ
data-prefetch=”true”
を設定する

<a href="next.html">次へ</a>

ただし、プリフェッチ機能を乱用すると
ユーザーが見ない画面も取得してしまうため
サーバーに負荷がかかるし
ネットワーク負荷もかかる
このため
プリフェッチ機能は、次にみる可能性の高い画面のみ設定すること

ちなみに、photoSwipeは
デフォルトで画像を表示している間にプリフェッチ機能で前後の画像を取得している

このため、画像をプリフェッチしながら表示するなら
PhotoSwipeを使うと便利

いろいろと使えそうなプリフェッチ機能だけと
アプリケーションキャッシュを使えば
プリフェッチ機能は使わなくても代用できる

$.getScript()で遅延ロード

$.getScript()でスクリプトの遅延ロード

大きなサイズのJavascriptライブラリーを使う場合
scriptタグで全部読み込むより
一旦画面を表示してから
スクリプトを読み込んだほうがWebアプリのレスポンスがよくなる

また、特定条件のときのみ必要なライブラリーは
ライブラリーを動的に読み込むようにして
不要なJavascriptのロードを避ける

Javascriptを動的に読み込むのに使うのが
$.getScript()
を使う

例えば、iOSでは日付が使えるけど
Androidではできない
なので、Androidなら
jQueryMobile DateBoxを読み込む
というように、ifで判定して使う

<script>
if(navigator.userAgent.indexOf("Android")!=-1){

$.getScript("http://dev.jtsage.com/cdn/datebox/latest/jquery.mobile.datebox.min.js",function(data,status){
$.getScript("http://dev.jtsage.com/cdn/datebox/i18n/jquery.mobile.datebox.i18n.ja.utf8.js",function(data,status){
//Javascript読みこみ処理

});

});

}
</script>

jQueryMobileでは、デフォルトで最初にアクセスしたとき
トップページでJavascriptを読み込むのが望ましい

そして、このときにトップページに必要のないJavascriptは
$.getScript()
を使うことで
まずはトップページを表示して
その後に必要なJavascriptを読み込むようにすれば
低速回線でもストレスなく表示することができる

フォームの遅延ロード

フォームの遅延ロード

Ajaxのフォームも遅延ロードで作成可能

ただし、これもただ追加しただけでは
jQueryMobileが適用されないため

フォームコンポーネントを追加した時点で
trigger(“create”)
を呼び出す必要がある

$.ajax({
type:"POST",
url:"./form.html",
dataType:'html',
success: function(data){

//データ追加
$("#corapsible-form").append(data);

//jQueryMobile反映
$("#corapsible-form").trigger("create");

},
error:function(msg){
alert(msg.responseText);
}

});

これで、あとはhtmlで
追加する領域の指定

<div data-role="corapsible" data-corapsed="true" id="acordion" name="acordion">
<h3>動的フォームの挿入</h3>
<form id="corapsible-form"></form>
</div>

続いて、挿入するhtmlファイル

このやり方のメリットは、後から追加できるため
メンテナンスが楽なこと
そして作業の分担ができること

全体的なUIの設定と
フォーム内容担当を分けることができる

アンケートなどではかなりの量になるので
都度アンケート内容だけ変更することもできる

<div data-role="fieldcontain">
<label for="slider">スライダー</label>
<input type="range" name="slider" id="slider" value="0" min="0" max="100" />
</div>

<fieldset data-role="controlgroup">
<legend>好きなタイプは?</legend>
<input type="checkbox" name="rpg" id="rpg" class="custom"/>
<label for="rpg">RPG</label>

<input type="checkbox" name="action" id="action" class="custom"/>
<label for="action">アクション</label>

<input type="checkbox" name="puzzle" id="puzzle" class="custom"/>
<label for="puzzle">パズル</label>

</fieldset>

<div data-role="fieldcontain">
<fieldset data-role="controlgroup">
<legend>使うosは?</legend>

<input type="radio" name="os" id="android" value="android"/>
<label for="android">Android</label>

<input type="radio" name="os" id="ios" value="ios" checked="checked"/>
<label for="ios">iOS</label>

<input type="radio" name="os" id="other" value="other"/>
<label for="other">両方</label>
</fieldset>
</div>

遅延ロードで必要なデータのみ取得

遅延ロードで必要なデータのみ取得

大量のデータや読みこみに時間がかかるデータを画面に表示するときに
かなり時間がかかる

この場合、最低限の画面を表示し
徐々にデータを表示したり
ユーザーがWikipediaのコンテンツみたいに
アコーディオンを開いたらオンデマンドで
データを取得、表示するという遅延ロードが有効

すごい時間をかけて全部でるより
徐々に表示されるほうがストレスは少ない

jQueryMobileで、
リスト表示で
この遅延ロードをするにはコツがある

なぜなら
Javascriptで後からタグを追加しただけだとjQueryMobileのスタイルが適用されないから

なので、追加したら
listview(“refresh”)
をする必要がある

まず、実践するには

<script src="js/loadform.js"></script>

で自作スクリプトの読みこみ

次に、開閉したい場所の領域を

<div data-role="corapsible" data-corapsed="true" id="corapsible-list">
<h3>遅延ロードの実践</h3>
<ul data-role="listview" id="list">
</ul>
</div>

として設定

data-role=”corapsible”
は、開閉する指定

data-corapsed=”true”
で開いた状態にする
デフォルトは false で閉じた状態

http://dev.screw-axis.com/doc/jquery_mobile/components/content/collapsible/
を参考にするとわかりやすい

そして、処理はJavascript

途中で
$.mobile.showPageLoadingMsg()

$.mobile.hidePageLoadingMsg()
があるけど、これは
ローディングアイコンの表示、非表示をする

この動作サンプルとしては
http://www.atmarkit.co.jp/fdotnet/chushin/jqmobile_06/jqmobile_06_02.html
にTwitterのつぶやきを表示したりするサンプルがあるので
こちらを参考にするとわかりやすい

あと
data: “param1=123&param2=homuhomu”
これは
http://semooh.jp/jquery/api/ajax/jQuery.ajax/options/

http://phpjavascriptroom.com/?t=ajax&p=jquery_ajax_requests

jQuery $.ajaxでJSON・JSONP読み込みに使用する主なオプション


をみたかんじだと
サーバーip/json.php?param1=123&param2=homuhomu
になる

$.trim()

http://semooh.jp/jquery/api/utilities/jQuery.trim/str/
にあるように、空白の削除するメソッド
つまり
if($.trim($(“#list”).html()) ==””){
なら
id=”list”のタグの中身が空ならとなる

$.each()は
http://semooh.jp/jquery/api/utilities/jQuery.each/object%2C+callback/
にあるように、繰り返し処理をする
繰り返すのは
$(‘#list’).append(“

  • “+data[e]+”
  • “);
    でリスト追加処理

    $(document).on("expand","#corapsible-list",function(e,data){
    if($.trim($("#list").html()) ==""){
    $.mobile.showPageLoadingMsg();
    
    $.ajax({
    type:"POST",
    url:"./json.php",
    data:"param1=123&param2=homuhomu",
    dataType:'json',
    success:function(data){
    $.each(data,function(e){
    $('#list').append("<li>"+data[e]+"</li>");
    });
    $('#list').listview("refresh");
    $.mobile.hidePageLoadingMsg();
    },
    error: function(msg){
    alert(msg.responseText);
    $.mobile.hidePageLoadingMsg();
    }
    
    });
    
    }
    
    });
    

    そして、PHPファイルでデータの用意
    ファイル名は json.php

    <?php
    header('Content-type: application/json;charset=utf-8');
    $data = array("みかん","りんご","ブドウ","もも");
    echo json_encode($data);
    ?>
    

    json_encode()
    で配列をjson形式にしている

    Webアプリの通信量削除

    Webアプリのパフォーマンスチューニング

    まず、通信量の削減

    基本的に、ライブラリーを使うときには
    .min.js
    とついている圧縮版を使う

    自作のコードもできる限りツールや
    Webサーバーのモジュールで圧縮する

    圧縮にはgruntのプラグインなども使えそう

    あと、使われる物としては
    Google Closure CompilerでJavascriptのコード削減

    YUI Compressor によるJavascriptとスタイルシートのコード削減

    Apache のmod_deflate によるデータ圧縮など

    ただし
    Google Closure Compiler
    YUI Compressor
    についてはJavaが必要になる

    Google Closure Compilerは
    https://code.google.com/p/closure-compiler/
    を参考に

    また、Google Closure Compilerは、コマンドからの操作も可能

    http://www37.atwiki.jp/aias-closurecompiler/pages/16.html?&flag_mobilex=1
    の解説がわかりやすい

    このツールは
    改行などを削除し、コードを圧縮する

    使い方は

    java -jar compiler.jar --js ファイル名

    結果をファイルへ出力するには

    java -jar compiler.js --js ファイル名 --js_output_file 出力ファイル名
    

    とする

    また、ファイルを結合するなら

    java -jar compiler.js --js_output_file 出力ファイル名 元のファイル名 元のファイル名

    とする

    次に、YUI Compressor
    これは、Yahoo!が開発している
    Javascriptとスタイルシートの圧縮ツール

    詳しい使い方については
    http://stacktrace.jp/tools/yuicompressor/
    を参考に

    これも、コマンドから実行で行う

    CSSファイルを圧縮するには

    java -jar yuicompressor.jar --type css --charset utf-8 -o 出力ファイル名 圧縮したいファイル名

    となる

    これも2つのソースをまとめることが可能で

    jar -jar yuicompressor --type css --charset utf-8 -o 出力ファイル名 元ファイルその1 元ファイルその2

    とする

    次に、データ圧縮をする Apache mod_deflateについて

    HTTP 1.1をサポートするWebサーバーを使うと
    サーバー側で自動的に圧縮したデータをブラウザー側で解凍して表示できる

    Apacheの場合
    mod_deflateモジュールを使うことでできる

    まずは、http.conf
    つまり、Apache設定ファイルの中にモジュール読み込み設定があるか確認

    LoadModule deflate_modules/mod_deflate.so
    

    そして、
    http://httpd.apache.org/docs/2.2/ja/mod/mod_deflate.html#deflatecompressionlevel
    のリファレンスを参考に追記する

    DeflateCompressionLevel
    の値は、1~9で
    値を大きくすれば圧縮率はあがるけど
    代償としてサーバーの負荷も上がっていく