この記事では「コーダーが対応できるサイトの表示速度向上」についての具体的な手法を紹介していきます。
サイトの表示速度はユーザー体験を大きく左右し、サイトの種類によってはUI(サイトの見た目)より重要視される場合もあります。
2017年にはGoogleが「ページの読み込み速度によって離脱率が変わる」と発表しました。
・1〜3秒の離脱率:32%
・1〜5秒の離脱率:90%
・1〜6秒の離脱率:106%
・1〜10秒の離脱率:123%
引用:https://www.thinkwithgoogle.com/
このようにサイトの表示速度はとても重要な指標になります。
サイトの表示速度向上には様々な手法が存在して、効果が出やすいものもあれば出にくいものもあり、実際に本番反映してみないと結果が分からないものもあります。また、難易度や実務上で許可を貰いやすいかなども考えなくてはいけません。
これらを踏まえ、効果が出やすく、対応もしやすい方法から順番に解説していきます。
サイトの表示速度やパフォーマンスを計測するにはGoogleが提供する「PageSpeed Insights(ページスピードインサイト)」を使います。

PageSpeed Insightsは、Webバージョンとデベロッパーツールバージョンがあります。
Webバージョンでは、PageSpeed InsightsにアクセスしてURLを入力するだけで使えます。
デベロッパーツールバージョンでは、デベロッパーツールを開いて要素やコンソールなどのタブメニューに「Lighthouse」という項目があるので、そこから使えます。
!計測結果の点数をより良い数値にすることも大切ですが、実際にページが表示されるまでの「体感時間」を短くすることも重要です。なので、点数が低い=絶対悪というわけでは決して無く、時には点数が低くてもページの表示速度を優先する場合もあります。
具体的な表示速度向上の解説の前に、まずはどのようにサイトの表示速度が決まるかを簡単に解説していきます。
フロントエンド側で表示速度に影響を与える指標は主に4つあります。
1つ目の「リクエスト回数」とは、CSSや画像などのファイルをサーバーからダウンロードする回数のことです。ダウンロードの回数が多ければ多いほど、つまり、サイトに読み込んでいるファイル数が多いほどサイトの表示に時間がかかります。 なので、読み込むファイル数を減らすことで表示速度が向上します。

リクエスト回数のイメージ図
2つ目の「リクエストサイズ」とは、サーバーからダウンロードしてくるファイルなどのサイズのことです。ファイルサイズが大きいほどサイトの表示に時間がかかります。 なので、ファイルサイズを小さく(圧縮)することで表示速度が向上します。

リクエストサイズのイメージ図
3つ目の「リクエストタイミング」とは、サーバーからファイルをダウンロードするタイミングのことです。通常、サイトを訪れたタイミングで全てのファイルを読み込みます。それに対して、画面外の画像の読み込みを遅らせるなど、リクエストのタイミングをズラすことでサイトを訪れたタイミングのダウンロード量(リクエストの回数やサイズ)を減らせます。 このように画像などのファイルの読み込みをズラすことを「遅延読み込み」や「非同期読み込み」と言います。

リクエストタイミングのイメージ図
4つ目の「HTMLパースの速度」とは、ブラウザがHTMLファイルを解析してDOMツリーを作成する速さのことです。解析中にファイル(CSS、JavaScript、画像など)が見つかると、ダウンロードが終わるまで解析はストップします。つまり、ファイルのリクエスト回数やサイズが大きいほどHTMLパースの完了が遅くなります。
https://coliss.com/articles/build-websites/operation/work/how-the-browser-renders-a-web-page.html
https://zenn.dev/ak/articles/c28fa3a9ba7edb#全体の流れ
なので、これまでに解説した1〜3を改善することで4のHTMLパースの速度が速くなり、その結果、サイトの表示速度が速くなります。
一番手軽で、かつ一番効果が出やすいのが画像の圧縮です。
サイト容量の半分以上は画像が占めています。画像のサイズを圧縮することで、リクエストサイズを小さくできます。
画像の圧縮には外部サービスを使うのが一般的だと思います。
https://www.iloveimg.com/ja/compress-image
他にも、GulpやWebpackを使った方法もあります。これらの良いところは、ローカル環境で完結し、ファイル名やフォルダ構造をそのままの状態で圧縮できる点です。外部サービスにアップロードする方法に限界が来たら、これらの方法を試してみるのもいいと思います。
https://ics.media/entry/220204/
https://www.asobou.co.jp/blog/web/gulp-imagemin
画像の圧縮も重要ですが、適切な拡張子を使うことも重要です。写真ならjpg、ベタ塗りや透過ならpng、ベクターならsvgなど、画像に適した拡張子を使うことも意識してみてください。
また、画像の圧縮率や拡張子によっては画像がぼやける場合もあるので、状況に応じてうまく対処できるようにしましょう。
画像まわりでもう一つ効果が出やすいのが、画像の遅延読み込みです。遅延読み込みをすることで、ページ読み込み時のリクエスト回数とリクエストサイズを減らすことができます。
imgのloading属性を使うことで、ブラウザが画像を表示する必要があるまで(例えば、ビューポート内に画像が入るまで)読み込み(ダウンロード)を遅らせることができます。
ひとつ例を紹介すると、ページ読み込み時のスクロール位置がファーストビューの場合、それより下に配置している画像はページ読み込み時の段階では見えないので読み込まれず、スクロールして画面内に表示されそうになったら画像が読み込まれます。
デベロッパーツールの「ネットワーク」タブを開いた状態で、loading="lazy"を使ったサイトを見てみるとイメージが湧きやすいと思います。スクロールしていくとどんどん画像が読み込まれていくはずです。
具体的な書き方は以下のようになります。
<imgsrc="path/to/img.png"alt=""width="600"height="300"loading="lazy"decoding="async"/>loading="lazy"を付けることで遅延読み込みになります。また、decoding="async"を付けることで画像のデコードを非同期化します。これらを使うにはwidthとheightは必須になります。
画像のデコードとは、画像が読み込まれた後、その画像をブラウザにレンダリング可能な形式に変換する処理のことです。decoding="async"を付けないと、重い画像をデコードするのに時間がかかり、その処理が終わるまでHTMLの読み込みをブロックしてしまいます。
<img>タグのwidthとheightはコアウェブバイタルのレイアウトシフト対策にもなるので、基本的には付けるようにしましょう。
loading="lazy"とdecoding="async"どちらも付けると、loading="lazy"が優先されます。ファーストビューの画像にはdecoding="async"を、それ以降の画像にはloading="lazy"を付けるのが良いです。
ファーストビューの画像もloading="lazy"にしてしまうと、本来真っ先に読み込みたい画像なのに読み込みが遅れてしまうので、画像の表示にタイムラグが生じてしまいます。
これらの属性は正しく扱わないと画像が表示された時の見え方がおかしくなったりするので、正しく理解してから使うようにしましょう。
decoding属性の私の解釈は少し違っていたみたいです。画像のデコードが完了しなくても、その下のHTMLは読み込まれるみたいです。
decoding属性に関してはキテレツさんの記事でとても詳しく解説されているので是非読んでみてください。
https://zenn.dev/ixkaito/articles/deep-dive-into-decoding
CSSやJavaScriptなど読み込ませるファイルを減らせば、リクエスト回数とリクエストサイズを減らすことができます。
何年も運用しているサイトの場合、使っていないファイルを読み込んでいることが多いので、改修する際に見直してみましょう。
また、外部プラグインは保存したファイルを読み込ませるのではなく、キャッシュを利用できるCDN(Content Delivery Network)で読み込ませるのがおすすめです。
https://news.mynavi.jp/techplus/article/zerojavascript-15/
CSSやJavaScriptのファイルをひとつにまとめるのも効果的です。意識するべき点を以下にまとめました。
@importは使わず、ひとつのファイルに全てのスタイルを記述する<script>タグにdefer属性を付与することで、HTMLパースを止めずにJavaScriptを読み込ませることができます。それにより、HTMLパースが通常より速く完了します。
<scriptsrc="path/to/script.js"defer>defer属性に関する解説はこちらの記事がとても分かりやすいので是非読んでみてください。
https://qiita.com/phanect/items/82c85ea4b8f9c373d684
また、HTMLファイルを読み込んでからブラウザに表示されるまでの仕組みを理解することも重要です。これらを正しく理解できれば適切な方法でサイト高速化を行えるようになります。
https://qiita.com/tanaShoe/items/f2d8f3d2ae034a094f99
ページ読み込み時に実行されるJavaScriptの処理を見直すことで、HTMLパースが速くなります。
見直すポイントをいくつか挙げてみたので、リファクタリング(コードの見直し)の参考にしてみてください。
setTimeout()で◯秒後に実行...のようにしていないか画面幅に応じて画像を切り替えるときは、display: noneで表示を切り替えるのではなく、<picture>タグを使います。
display: noneで切り替える場合、表示されるのは片方の画像だけでも両方の画像が読み込まれているので、その分無駄な読み込みが発生しています。
<imgclass="pc"src="path/to/pc.png"><imgclass="sp"src="path/to/sp.png"><picture><sourcesrcset="path/to/md.png"media="(min-width: 768px)"><imgsrc="path/to/sm.png"></picture>https://b-risk.jp/blog/2022/09/picture-srcset/#picture_source
!画面幅に応じたクラス名やファイル名の命名についてpc,spなどの具体的な名前にするより、sm(small),md(medium),lg(large)のような抽象的な名前にしたほうが汎用性が高く使いやすくなります。
参考:Tailwindのブレイクポイントの変数名(https://tailwindcss.com/docs/screens)
MacやiPhoneなどの高解像度(Retina)ディスプレイで画像をキレイに表示するには表示サイズの倍の解像度が必要になるので、その分ファイルサイズが大きくなってしまいます。
srcset属性を使うことで、解像度(デバイスピクセル比)に応じた画像の切り替えが可能になり、リクエストサイズを減らせます。
<imgsrcset="path/to/sm.jpg 640w, path/to/md.jpg 767w, path/to/lg.jpg 1080w"src="path/to/lg.jpg"sizes="(max-width:1080px) 100vw, 1080px"/>こちらの記事で詳しい使い方が解説されているので参考にしてみてください。
https://ics.media/entry/13324/#レスポンシブイメージにおける画像出し分け
srcset属性を使うには、1枚の画像に対して複数の解像度の画像が必要で、これを自分で用意するのはかなり大変です。
ほとんどの場合、プラグインを導入したりツールで一括生成したりしているので、srcset属性を使う際は「各解像度の画像をどうやって用意するか」も検討する必要があります。
CSSファイルのサイズが膨大な場合、レンダリングブロックが発生してブラウザに描画されるまでの時間が長くなってしまいます。
https://www.1-firststep.com/archives/9806
<link>タグにmedia="print" onload="this.media='all'"を追加することで、CSSが非同期読み込みになりレンダリングがブロックされなくなります。
<linkrel="stylesheet"href="path/to/style.css"media="print"onload="this.media='all'">https://qiita.com/rana_kualu/items/95a7adf8420ea2b9f657
この方法を行うと、ページ読み込み時に一瞬だけスタイルが当たらずレイアウトが崩れている状態でブラウザに表示される場合があります。なので、ページ読み込み時に見える部分(メインビジュアルなど)のCSSは<head>の中に<style>でインラインで読み込ませたりなど工夫が必要です。
また、コアウェブバイタルの「CLS」の指標が著しく悪くなるケースもあるので、メリット・デメリットを正しく理解したうえで実行するようにしましょう。
iframeも画像と同様に遅延読み込みが可能です。
<iframesrc="https://example.com"loading="lazy"width="600"height="400"></iframe>ひと昔前は、画像やiframeを遅延読み込みさせるにはプラグインが必要でしたが、昨今のブラウザではloading="lazy"のサポートが一般化してきたので、わざわざプラグインを使わないでもよくなりました。
これまでに解説した内容の他にも表示速度改善の施策はたくさんあります。しかし、ひとつずつ解説していたら膨大な量になってしまうので、残りは箇条書きベースで簡単に紹介していこうと思います。
<symbole>と<use>を使ってインラインで埋め込むサイトの表示速度に影響を与えるのは画像が大半です。 この記事で紹介した内容も9個中4個(10番目は除く)は画像に関することです。なので、画像はちゃんと圧縮する、正しい拡張子を使う、適切な大きさにする、遅延読み込みをする、だけでかなり変わるはずです。
他にはファイル読み込みに関する内容も多かったと思います。当たり前のことですが、意外とできていないのが「不要なファイルは読み込まない」です。サイトの歴史が長くなればなるほど不要なファイルは増えていきます。これらとうまく付き合うのも表示速度向上のポイントのひとつです。
今回紹介した内容(特に1〜9)を対応してもサイトの表示速度が変わらない場合、利用しているフレームワーク(WordPressやJSライブラリ)の書き方や大元に問題があったり、サーバーサイドに何らかの原因があると考えられます。
聞き慣れない用語も多かったと思うので、用語の意味を調べながらこの記事を読んでもらうとより深く理解できると思います。
バッジを受け取った著者にはZennから現金やAmazonギフトカードが還元されます。