背景
- 先週から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します。上記記事からコードの大部分をお借りしております。
(function(window,document){functioninsertResource(){// twitterの読み込みvartw_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の読み込みvaryoutube=document.createElement('iframe');youtube.className="youtube__iframe";youtube.src="https://www.youtube.com/embed/xxxxxxxxx";youtube.frameborder=0youtube.allow="autoplay; encrypted-media"youtube.allallowfullscreenow=""document.getElementById('js-youtube').appendChild(youtube);// 対象のページに<div id="js-youtube"></div> を埋め込んでおく}// 遅延読込みvarlazyLoad=false;functiononLazyLoad(){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
自体を通常の遅延読み込みで埋め込みます。
<script type="text/javascript"src="/js/lazy_load.js"defer="defer"/>
3. CSS と WebFont の遅延ロード
defer
を使えば簡単にできるjavascriptの遅延ロードと違って、CSSの遅延ロードはちょっと面倒ですよね。
以下の記事で簡単な方法が紹介されていたので、活用しました。
media="print" onload="this.media='all'"
を追加するだけ。便利。
以下は Uikitのcssを埋め込む時の例です。
<linkrel="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'"
を追記する
<linkrel="preconnect"href="https://fonts.gstatic.com"><linkhref="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。
<pictureclass="thumb"><sourcesrcset="/img/top/thumb.webp"type="image/webp"><imgclass="image"src="/img/top/thumb.jpg"loading="lazy"/></picture>
問題は CSSの background-image などで画像を指定している場合ですね。
modernizr.jsを使用することで、ブラウザの対応状況に合わせてCSSを切り替えることができます。詳しくは以下記事をどうぞ。
5. Resource Hintsの使用
そこまでやる必要があるのかはよくわからなかったんですが、 Resource Hintsなるものを使うことで、必要になるであろうリソースを先にブラウザに伝えることができるようです。
今回の場合、ファーストビューのメインビジュアル画像をCSSのbackground-imageで指定してたので、HTML -> CSS -> 画像ファイルという3工程のリクエストチェーンになってしまうので、読み込み開始を早めるために使用しました。
<linkrel="preload"href="/img/top/mainvisual.webp"as="image">
これにより、ファーストビューのメインビジュアル画像のリクエストチェーンを HTML -> 画像ファイルの2工程に短縮できます。
体感でしかないけど、ファーストビューの表示がちょっとだけ早くなったような気はする。
結果
これだけやったところ、5/100点から50/100点にまでは上がったんですが、まだ Largest Contentful Paint(LCP) の点数が辛くてそれ以上にはならないようです。なんでなんや・・・。
もうちょっと勉強したらまた続きを書こうと思います。