背景
- 先週からWebページ高速化を勉強しはじめて、なんとか最初の改善リリースを終えました。
- TOPページとLPをリニューアルしたのですが、表示速度が極端に低くなった(PageSpeed Insights
で5/100点!)ため、急いでWebページ高速化に取り組まざるをえなくなった。最終的には数日程度で50点近くまで上げることができた。
- TOPページとLPをリニューアルしたのですが、表示速度が極端に低くなった(PageSpeed Insights
- とにかく急いでやったプロジェクトだったんですが、似たような状況に追い込まれた人のために、やったことを残しておきます。
やったこと
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) {
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
自体を通常の遅延読み込みで埋め込みます。
<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を埋め込む時の例です。
<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")でも同様のことができます。
- Google Fonts から 埋め込み用のタグを取得
-
media=”print” onload="this.media='all'"
を追記する
<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。
<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を切り替えることができます。詳しくは以下記事をどうぞ。
5. Resource Hintsの使用
そこまでやる必要があるのかはよくわからなかったんですが、 Resource Hints なるものを使うことで、必要になるであろうリソースを先にブラウザに伝えることができるようです。
今回の場合、ファーストビューのメインビジュアル画像をCSSのbackground-imageで指定してたので、HTML -> CSS -> 画像ファイル という3工程のリクエストチェーンになってしまうので、読み込み開始を早めるために使用しました。
<link rel="preload" href="/img/top/mainvisual.webp" as="image">
これにより、ファーストビューのメインビジュアル画像のリクエストチェーンを HTML -> 画像ファイル の2工程に短縮できます。
体感でしかないけど、ファーストビューの表示がちょっとだけ早くなったような気はする。
結果
これだけやったところ、5/100点から50/100点にまでは上がったんですが、まだ Largest Contentful Paint(LCP) の点数が辛くてそれ以上にはならないようです。なんでなんや・・・。
もうちょっと勉強したらまた続きを書こうと思います。