LoginSignup
2
3

More than 3 years have passed since last update.

Webページ表示速度高速化、始めます!

Last updated at Posted at 2020-11-15

背景

  • 先週からWebページ高速化を勉強しはじめて、なんとか最初の改善リリースを終えました。
    • TOPページとLPをリニューアルしたのですが、表示速度が極端に低くなった(PageSpeed Insights で5/100点!)ため、急いでWebページ高速化に取り組まざるをえなくなった。最終的には数日程度で50点近くまで上げることができた。
  • とにかく急いでやったプロジェクトだったんですが、似たような状況に追い込まれた人のために、やったことを残しておきます。

やったこと

1. 「初歩からのPageSpeed Insights」 を読む

とりあえずまず以下の本を読みました。

重いサイトを軽くする、Webページ表示速度の高速化10の基本: 初歩からのPageSpeed Insights (にししふぁくとりー叢書)

  • Amazon Unlimitedに加入してれば無料で読める
  • 少ない分量でまとまっている。
  • 全部読まなくても、自分に関係がありそうな部分だけを拾い読む -> 可能な施策だけ着手 の流れが容易。

まずは、この本の内容と、自分のWebサイトのPageSpeed Insightsの結果を見比べて、効果がありそうなものから着手していきました。基本的な知識は全部この本で得られたので、この記事では、上記の本で足りなかったことを解説していきます。

2. 外部js, youtubeなどの超遅延ロード

超遅延ロード というのは私の造語ですが、 defer などを用いた単なるjsの遅延ロードではなく、「Userが何らかのアクションをしたらロードする」というアクロバティックな遅延ロード手法です。この記事で紹介されてました。

うちのサイトの場合、tweetのjavascriptの埋め込みyoutubeの埋め込み が表示速度の悪化の大部分の原因を占めていたので、 これが最も効果があった施策でした。(あと、tweetとyoutubeはページのかなり下の方のコンテンツだったので、ロードを遅らせる合理的な理由もありました)

以下のコードで、Userの何らかのアクションに引っかけて、<script> タグや <iframe> などのDOMをinsertします。上記記事からコードの大部分をお借りしております。

lazy_load.js
(function(window, document) {
  function insertResource() {

    // twitterの読み込み
    var tw_script = document.createElement('script');
    tw_script.type = 'text/javascript';
    tw_script.defer = true;
    tw_script.src = 'https://platform.twitter.com/widgets.js';
    document.getElementById('js-twitter-load').appendChild(tw_script); // 対象のページに<div id="js-twitter-load"></div> を埋め込んでおく

    // youtubeの読み込み
    var youtube = document.createElement('iframe');
    youtube.className = "youtube__iframe";
    youtube.src = "https://www.youtube.com/embed/xxxxxxxxx";
    youtube.frameborder = 0
    youtube.allow = "autoplay; encrypted-media"
    youtube.allallowfullscreenow = ""
    document.getElementById('js-youtube').appendChild(youtube); // 対象のページに<div id="js-youtube"></div> を埋め込んでおく
  }

  // 遅延読込み
  var lazyLoad = false;
  function onLazyLoad() {
    if (lazyLoad === false) {
      // 複数呼び出し回避 + イベント解除
      lazyLoad = true;
      window.removeEventListener('scroll', onLazyLoad);
      window.removeEventListener('mousemove', onLazyLoad);
      window.removeEventListener('mousedown', onLazyLoad);
      window.removeEventListener('touchstart', onLazyLoad);
      window.removeEventListener('keydown', onLazyLoad);

      insertResource();
    }
  }
  window.addEventListener('scroll', onLazyLoad);
  window.addEventListener('mousemove', onLazyLoad);
  window.addEventListener('mousedown', onLazyLoad);
  window.addEventListener('touchstart', onLazyLoad);
  window.addEventListener('keydown', onLazyLoad);
  window.addEventListener('load', function() {
    // ドキュメント途中までスクロールしている場合(更新時 or ページ内リンク)
    if (window.pageYOffset) {
      onLazyLoad();
    }
  });
})(window, document);

あとは lazy_load.js 自体を通常の遅延読み込みで埋め込みます。

index.html
<script type="text/javascript" src="/js/lazy_load.js" defer="defer" />

3. CSS と WebFont の遅延ロード

defer を使えば簡単にできるjavascriptの遅延ロードと違って、CSSの遅延ロードはちょっと面倒ですよね。
以下の記事で簡単な方法が紹介されていたので、活用しました。

CSSを非同期ロードする最も簡単な方法

media="print" onload="this.media='all'" を追加するだけ。便利。

以下は Uikit のcssを埋め込む時の例です。

index.html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.5.9/dist/css/uikit.min.css" media="print" onload="this.media='all'" />

WebFont(例:GoogleFontsの"Noto Sans JP")でも同様のことができます。
1. Google Fonts から 埋め込み用のタグを取得
2. media=”print” onload="this.media='all'" を追記する

index.html
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap" rel="stylesheet" media=”print” onload="this.media='all'">

ファーストビューの描画に必要なCSSだけを同期的に読み込み、それ以外のCSSやWebFontは全部遅延読み込みにしてしまいます。

4. .webp 形式の画像の導入

上記までの施策で、うちのサイトの点数はだいたい改善されたのですが、残ったのが画像の重さ問題。
PageSpeed Insightsがしつこく勧めてくるので、.webp形式の画像の導入を決めました。
.webp 形式は .jpg や .png より軽いのが利点ですが、対応していないブラウザも多いので、他の形式の画像と併用する必要があります。

<img> タグを使用している場合は、以下の書き方でOK。

index.html
<picture class="thumb">
  <source srcset="/img/top/thumb.webp" type="image/webp">
  <img class="image" src="/img/top/thumb.jpg" loading="lazy" />
</picture>

問題は CSSの background-image などで画像を指定している場合ですね。
modernizr.jsを使用することで、ブラウザの対応状況に合わせてCSSを切り替えることができます。詳しくは以下記事をどうぞ。

WebP(ウェッピー)を導入してみよう

5. Resource Hintsの使用

そこまでやる必要があるのかはよくわからなかったんですが、 Resource Hints なるものを使うことで、必要になるであろうリソースを先にブラウザに伝えることができるようです。
今回の場合、ファーストビューのメインビジュアル画像をCSSのbackground-imageで指定してたので、HTML -> CSS -> 画像ファイル という3工程のリクエストチェーンになってしまうので、読み込み開始を早めるために使用しました。

index.html
<link rel="preload" href="/img/top/mainvisual.webp" as="image">

これにより、ファーストビューのメインビジュアル画像のリクエストチェーンを HTML -> 画像ファイル の2工程に短縮できます。
体感でしかないけど、ファーストビューの表示がちょっとだけ早くなったような気はする。

結果

これだけやったところ、5/100点から50/100点にまでは上がったんですが、まだ Largest Contentful Paint(LCP) の点数が辛くてそれ以上にはならないようです。なんでなんや・・・。
もうちょっと勉強したらまた続きを書こうと思います。

参考

2
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3