NuxtにLazyLoadを入れてみた

2019/3/5 追記

LazyLoadを導入しましたが、サイト速度が向上したかに関して、現状測定していません。 Page Speed Insight の点数が向上したという結果のみ得ています。 そのため、実際にパフォーマンス向上に貢献できているかは不明です。

Webパフォーマンスの振り返り 2018 - Webパフォーマンスについて 上記のtakehora様の記事にあるように、<img decoding ="async">を用いる方がいいのではないかと思います。 (ただ、そこに関しても自身で測定できてないので、全体のパフォーマンス測定したら追記します。)

経緯

画像がいっぱい表示されるサイトをNuxt&SSRで、作っている。 なので、画像を読み込む時間が結構かかって困ってた。 LazyLoadすればいいことはわかってたけど、SEOへの影響がよくわからなくて、プロダクト的にNGだった...

しかし、Googleが11月にこのような実装方法を出してくれたので、Goサインがでた! developers.google.com

やったこと

まず、VueLazyLoadがめっちゃ便利なので、それをインストール

github.com

import Vue from 'vue';
import VueLazyload from 'vue-lazyload';

Vue.use(VueLazyload, {
  preLoad: 1.1,
  attempt: 1,
  observer: true,

  observerOptions: {
    rootMargin: '0px',
    threshold: 0.1
  }
});

上記のように、pluginファイル作って、nuxt.config.js に ssr: false にして、追記 observerをtrueにすることが必要で、そうすると、Googleの解説記事にある ブラウザnativeの IntersectionObserver を使ってくれる。 ただ、これだけだとIEとか動かないので、app.htmlに、直接polyfillを追加した。

<script
    async
    src="https://cdn.polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"
></script>

困ったこと

初期表示時は、SSRしたもの画像が表示されるので、vue-lazyloadのマニュアル通りに、初期画像を設定しても上手くいかなかった。 なので、下のようなコンポーネント作って、Lazyload使うときは、常にこれ使うようにしたらいい感じになった!

<template lang="pug">
  img(src="~assets/images/background/pixel.png" :alt="alt" v-lazy="src")
</template>

<script>
export default {
  props: {
    src: {
      type: String,
      required: true
    },
    alt: {
      type: String,
      required: true
    }
  }
};
</script>

LazyLoadめっちゃ便利!

追記

下記の記事を見つけた。

画像の非同期デコーディング

Webパフォーマンスの振り返り 2018 - Webパフォーマンスについて

<img decoding ="async"> とつけると、画像デコーディングが非同期で行われ、ページ表示まで早くなるらしい。
自分の環境(通信速度が早い)だと、LazyLoadした時と比べて、初期表示とかの体感では変わらなかった。
むしろ、LazyLoadしてると、表示後画像が出るまでにどうしても遅れる(特に画像が大きい時)ので、しない方が体感としては良い。

一方、audit(lighthouse)で試してみたら、点数がLazyLoadと比較して、明らかに下がっていた。
ということは、page speed insight でも点数は下がるはずで、これがSEOとかに影響与えないか(多分ないはずだけど)不安。

ただ、ユーザ体験を考えると、LazyLoadないほうがいいのかもと思った。
あとは、コストの問題だなって感じ。
大規模にならないとあんまり変わんないけど。

将来は、LazyLoadがブラウザ標準になるっぽいから、<img decoding='async' lazyload='on'>という書き方がデフォルトになっていくのかも。