unoh.github.com

画像の遅延読み込み

Wed Jan 16 21:42:14 -0800 2008

yamaokaです。




webページの表示を高速化する手法にはいろいろありますが、
その一つとして遅延読み込みという手法があります。
初期状態で表示する必要のない要素については読み込まず、
必要になったタイミングで読み込み、表示するようにする手法です。




ページの読み込みにかかる時間の大半を
画像の読み込みが占めている場合が多いので、
画像の読み込みを遅延させるという手法が多く取られます。



検討するべきケース




では、画像の遅延読み込みはどのような場合に検討されるべきでしょうか。
最初から表示されている必要がない画像が存在し、その画像のサイズが大きかったり、
そうした画像の数が多い場合は検討してみる価値があると思います。




例えば、次のようなケースです。





仕組み




では、どのように画像の遅延読み込みを実現すればよいのでしょうか。
仕組みは単純です。




  1. 適当なタイミングで、読み込みたくない画像のimg要素のsrc属性の値を適当な画像(1ピクセル四方のGIF画像など)のパスに置き換える

  2. 表示が必要になったタイミングで、先ほど置き換えたsrc属性の値を元に戻し、実際の画像を読み込んで表示させる




これだけ。簡単ですね。




一番目の「適当なタイミング」とは、
ページ全体のDOMツリーの読み込みが完了したタイミングがいいでしょう。
そのタイミングで画像のimg要素のsrc属性を書き換えてしまうことにより、
その時点では不要な画像の読み込みを抑えることができます。
場合によっては、画像が属するブロックの読み込みが完了したタイミングで
実行してしまってもいいかもしれません。




二番目の「表示が必要になったタイミング」とは、
表示されていなかった要素が表示されるタイミングとか、
画面がスクロールされてきたとかそういうタイミングを指します。
そのイベントを検知して、画像を表示させればよいのです。



具体例




具体例として、idが「foo」のブロック要素に含まれる画像を遅延読み込みさせる場合を考えてみます。
prototype.jsをライブラリとして利用している場合、
次のように遅延読み込み処理を記述することができます
(便宜上、「Foo」を名前空間代わりに使用しました)。




Foo = {};
Foo.images = [];
Foo.stopLoadingImages = function() {
  $$("#foo img").each(function(image) {
    image.orgSrc = image.src;
    image.src = "1x1.gif";   // 小さな画像に置き換え
    Foo.images.push(image);  // 置き換えた要素をとっておく
  });
};
Foo.loadImages = function() {
  Foo.images.each(function(image) {
    image.src = image.orgSrc;  // 元の値に戻す
  });
};




あとは、「Foo.stopLoadingImages」と「Foo.loadImages」を
必要なタイミングで実行するようにするだけです。



ライブラリの紹介




実際には、何らかのライブラリを利用して遅延読み込みを実現する場合が多いでしょう。
主なライブラリとして、次のようなものがあります。






それぞれのライブラリでできることに違いがありますので、
既に自分が使っているライブラリとの適合性も含め、一度見てみるといいかもしれません。



まとめ




体感速度を少しでも速くするための手法として、画像の遅延読み込みは効果的です。
初期状態では画像に通常のimg要素が用いられるため、
JavaScriptが有効になっていない環境で閲覧された場合でも、何の副作用もありません。
必要に応じて導入を検討してみるといいのではないでしょうか。




2008年1月18日12:50追記

「仕組み」の「適当なタイミング」について加筆訂正を行いました。