サイト速度改善シリーズ画像編!
今回は画像を遅延して読み込む方法についてお話いたします。

💁‍♀️

画像を遅延して読み込むことでサイトの最初の表示速度を改善することができるよ





    Strory
  1. 画像の遅延読み込みとは
  2. おすすめの画像の遅延読み込み方法
    • ユーザーにも優しいIntersectionObserver
    • 簡単に実装ができるlazyload
    • IntersectionObserverとlazyloadのブラウザ対応

画像の遅延読み込みとは

まずページを表示するまでの一連の流れをみてみます。
簡単に流れを書くとこんな感じ↓

  • ファイルの読み込み
  • JavaScriptの実行
  • ファイルの装飾
  • 描画

任意のサイトにアクセスすると、サーバーに指定のファイルを取りに行って、読み込みが始まります。
ファイルの読み込みが終わるとDOM要素にCSSを当てたり、Javascriptの処理をしたりして、最後にブラウザ上に描く、とゆうような流れがあります。

ここで最初に行われるファイルの読み込みについて考えてみます。
もし、大量のコンテンツが掲載されたページにアクセスした時に、熱狂的なファンではない限りページの全てを読むかどうかはわからないですよね。 それなのにページ上のファイルの全ての読み込み時間分待つのは勿体無くないですか?

😢

確かに、すごく待ったのに期待していた内容じゃなかったら嫌だよね。

ここで画像ファイルの読み込みについて考えてみます。

読み込むファイルにはhtml、CSSなど様々なファイル形式がありますが、その中でも重いのが画像ファイルです。
ページ上の約6割の容量が画像ファイルだと言われています。

😭

じゃあ画像を減らせばいいの?でも見やすいサイトにするためにも画像はいっぱい使いたいな。

もちろん、いらいない画像は削除するべきですが、やっぱり画像は使用したいですよね。
対策としては極力いらない画像を使わない、画像圧縮やリサイズでファイルサイズを下げるなどありますが、実はページを表示した後に画像を読み込む手段があります。

それが今回のトピックである画像の遅延読み込みなのです。

画像の遅延読み込みは色々な方法があるので、その中でもおすすめの実装方法を2つご紹介します。

おすすめの画像の遅延読み込み方法

ユーザーにも優しいIntersectionObserver

まず一番私がおすすめしたい方法がIntersectionObserverというJavascriptのAPIです。
IntersectionObserverとは現在表示されている画面の位置を監視している警備員さんで、画像の位置まで画面がスクロールされたらその画像を読み込むというような処理ができます。

IntersectionObserverの良いところはサイトの速度改善だけではありません。
もし画像が表示位置にくる前にページを閉じてしまった場合、その画像の読み込みは発生しません。

😇

ユーザーが無駄にデータを消費するのを防げるんだね!

またGoogleさんもIntersectionObserverを推奨しており、googlebotもIntersectionObserverを理解できるようになる(なった?)とWeb Masterで公言されています。
Web Masterの記事の画像 The new evergreen Googlebot


IntersectionObserverはJavascriptのAPIで難しいと感じるかもしれませんが、手順は二つだけで簡単なのでぜひやってみてください。

  • 遅延読する画像のimgタグに同じclass名をつける&src属性を違う属性名に変える
  • IntersectionObserverのコードを書く

遅延読する画像のimgタグに同じclass名をつける&src属性を違う属性名に変える

例として遅延読み込みしたい画像のimgタグにclass名をimgを追加、srcをdata-lazyに変更します。

<html>
    ...
    <body>
        <img data-lazy="example.jpg" class="img">
        <img data-lazy="example.jpg" class="img">
        <img data-lazy="example.jpg" class="img">
    </body>
</html>

IntersectionObserverのコードを書く

以下のコードをhead内に貼り付けます。

<script>
    document.querySelectorAll(".img").forEach(target => {  #()内にclass名を入れる
        const io = new IntersectionObserver((entries, observer)=>{
            entries.forEach( entry =>{
                if(entry.isIntersecting){
                    const img = entry.target;
                    const src = img.getAttribute('data-lazy'); #()内に属性名を入れる
                    img.setAttribute('src', src);
                    observer.disconnect();
                }
            });
        });
        io.observe(target);
    });
</script>
4行目のquerySelectorAllの後の()内にimgタグに付けたclass名を.(ドット)+class名という形で書いてください。
また9行目のgetAttributeの後の()内にsrcを置き換えた属性名を入れてください。
このJavascriptがやっていることはclass名がimgの全てのimgタグを監視するようにして、 その要素が画面上の高さまできた時にdata-lazy属性をsrc属性に置き換えることで画像を表示しています。

注意点としてIEでは非対応なので、もしIEにも対応させたい場合は先ほどのscriptタグの上に以下のコードを貼り付けて置いてください。
<script src="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script>

簡単に実装ができるlazyload

いやいや、IntersectionObserver難しいよ、、、という方のために簡単に実装できるlazyloadもご紹介しておきます。
imgタグにはloading属性というものがあり、この属性にlazyを付けてあげるだけで、画像の遅延読み込みができます。

<img src="example.jpg" loading="lazy">

🤔

え、こっちの方が全然楽じゃない?

確かにlazyloadの方がIntersectionObserverより簡単に対応できます。
しかし、lazyloadを対応していないブラウザがあるので、注意が必要です。

IntersectionObserverとlazyloadのブラウザの対応状況

主要なブラウザの対応表
(2020年3月7日地点での情報)

ブラウザ IE
(11)
Edge
(80)
Firefox
(73)
Chrome
(80)
Safari
(13)
iOS Safari
(13.2)
Chrome for Android
(80)
IntersectionObserver ×
lazyload × × × ×

IntersectionObserverはIEのみが非対応となっていますが、IEもpolyfillを使えばカバーできます。
に対してlazyloadはIEに加えてsafari、Firefoxなどまだまだ非対応のブラウザが多いのが現状です。

🤔

一見、lazyloadの方が簡単に見え流けど、ブラウザ対応を考えるとIntersectionObserverの方が良さそうだね。

まとめ

画像の遅延読み込みとは何かから対応方法までご紹介しました。
画像ファイルはファイル形式の中でもサイズが比較的多いので、遅延読み込みの対応で速度改善に良い効果が期待できます。
また遅延読み込みさせる方法はIntersectionObserverとlazyloadの2種類お話しましたが、lazyloadはブラウザの対応がまだ追いついていないので、IntersectionObserverを使うのが良いかと思います。