2013/07/24更新

[パフォーマンス] 画像をLocalStorageへキャッシュして、Webページの表示を少し速くしてみる

このエントリーをはてなブックマークに追加            

こんにちは、@yoheiMuneです。
以前のブログで、「CSSとJSをLocalStorageにキャッシュして、2回目以降の表示を速くしてみる」を紹介させて頂きました。 今回はサイトで頻繁に利用する画像をLocalStorageへ保存することで、表示を高速化する方法をブログに書きたいと思います。

画像



画像をLocalStorageへ保存すると表示が速くなる?

画像やCSSやJSなどのファイルは、Expireヘッダなどを使ってブラウザへキャッシュすることが可能です。
ただ多くのスマホの場合、画面を開くたびにキャッシュ確認のためサーバーへ問い合わせを行ってしまい、そのリクエスト待ちで表示が遅れるのがもったいないのです。
ただしLocalStorageの上限が5MB程度のブラウザが多いので、たくさんのコンテンツをキャッシュで来ません。 良く利用する画像をキャッシュすることで、表示を高速化させてみようじゃないかというのが今回のブログの意図です。

また制約事項として画像をBase64としてLocalStorageへ保存するため、画像がクロスドメインにならないことが制約となります。



画像をLocalStorageへキャッシュする実装

実装は以下のように行います。まずはキャッシュ機能の実装です。
/**
  画像をlocalStorageへ保存して、キャッシュがある場合にはそちらを読む機能
*/
(function() {

  // namespace
  window.cacheModule = window.cacheModule || {};

  // alias
  var aCacheModule = window.cacheModule;
  var storage = window.localStorage;

  // LocalStorageがサポートされているかの判定式
  var supportStorage = storage;

  var PREFIX = 'yoheimcache:';
  var version = '?ver=3.0.3';


  // バージョンが変わっている場合には、キャッシュを削除する。
  (function() {
    if (supportStorage) {
      var ver = storage.getItem('yoheimVersion');
      if (ver !== version) {
        storage.clear();
        storage.setItem('yoheimVersion', version);
      }
    }
  })();



  // localStorage用のキー生成
  var createKey = function(str) {return PREFIX + str + version;}
  // バージョン付きのURL
  var urlWithVersion = function(url) {return url + version;}


  // 引数の内容から、imgタグを生成する。
  var createImgTag = function(src, cssClass, options) {
      var tag = '<img src="' + (src || '') + '" class="' + (cssClass || '') + '" ';
      for (var prop in options) {
        if (options.hasOwnProperty(prop)) {
          tag += ' ' + prop + '="' + options[prop] + '"';
        }
      }
      tag += '/>';

      return tag;
  }


  /*
    画像のロード
  */
  aCacheModule.loadImage = function(src, cssClass, options) {
    options = options || {};

    if (!supportStorage) {
      // LocalStorageがサポートされていない場合は、imgタグを出力する
      document.write(createImgTag(src, cssClass, options));
      return;
    
    } else {

      // LocalStorageにキャッシュがある場合、その画像を表示する
      var base64 = storage.getItem(createKey(src));
      if (base64) {
        document.write(createImgTag(base64, cssClass, options));
        return;
      
      } else {

        // LocalStorageにキャッシュが無い場合は、imgタグを出力する
        document.write(createImgTag(src, cssClass, options));

        // そして、その後画像を別途取得して、LocalStorageへ保存しておく
        window.addEventListener('load', function() {

          var canvas = document.createElement("canvas");
          if (!canvas || !canvas.getContext || !canvas.getContext('2d')) {
            return;
          }
          var image = new Image();
          image.src = src;
          image.onload = function() {

            // 画像をbase64にするためにCanvasを利用するので、
            // クロスドメインの画像は無理かも。。
            var canvas = document.createElement("canvas");
            canvas.width = this.width;
            canvas.height = this.height;
            canvas.getContext('2d').drawImage(this, 0, 0);
            var base64 = canvas.toDataURL();

            storage.setItem(createKey(src), base64);
          };
        }, false);
      }
    }
  };
})();
という感じです。画像をbase64にしてLocalStorageへ保存します。
続いて上記機能を利用する箇所です。以下のように利用します。
<div class="imgArea">
  <script>window.cacheModule.loadImage('image/self.jpg', 'someClass', {width: '50px', style:'float:right; padding-left:7px;'});</script>	
</div>
通常のimgタグの代わりに、window.cacheModule.loadImageメソッドを使って、画像のキャッシュ機能を利用します。
これを利用することで、1回目の画像ロードでLocalStorageへ保存して、2回目以降はLocalStorageキャッシュから表示することが出来るので、表示の速度の向上ができます。



最後に

画像をキャッシュする機能で、HTML5 App Cacheもありますが、今回は利用できませんでした。manifestファイルを指定しているHTMLもキャッシュされてしまう仕様が、今回は合わなかったためです。
Webの表示高速化は、これからも詳しく取り組んで、より簡単により効果的に高速化できるようにがんばりたいと思います。

最後までご覧頂きましてありがとうございました。





こんな記事もいかがですか?

RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。