PageSpeed Insights リニューアル後のスピード改善で実施したこと(静的HTMLサイト)

2018年11月にGoogleのPageSpeed Insights(PSI)が大幅リニューアルされた。LightHouseという今までChrome拡張などのオプションでしかなかったツールが標準導入され、チェック項目や採点の仕方が大きく変わったが、この対策についての情報が少なかったので、今回請け負った静的HTMLサイトの高速化で行なったことを記録に残しておきます。

次世代フォーマットでの画像の配信

jpg, jpeg, pngではなくGoogleが開発した新しいwebp形式の画像を表示するようにすればOK。

このwebp形式自体は数年前からあるが、現在ではChrome以外のブラウザ(Safariなど)では非対応らしい。そのためhtaccessの記述などでjpe?g/pngとwebpを対応非対応で出し分ける必要がある。

コードは「webp htaccess」などでググれば多く出回っている。 https://doocts.com/3288https://qiita.com/miyanaga/items/6570c3c9ae8e15dbb57c

今回の案件ではWordPressではなく静的なHTMLで記述したページの高速化だったので、先のリンクを参考にEWWW OptimizerでWebp形式に変換した画像をダウンロードし、それをサーバーにアップロード、2番目の参考リンクのhtaccessのコードを記述して、PSI上は警告が消えた(本当にChromeなどの対応ブラウザでWebp画像が読み込まれているかはChrome Developer ToolのNetworkタブを開いてページを再読み込みし、typeの列にwebpと表示されるかどうかで確認できる)。

追記

以下のWebサービスでも問題なく画像をwebpに変換してくれ、PSIの警告消えました。 https://lab.syncer.jp/Tool/Webp-Converter/

オフスクリーン画像の遅延読み込み

いわゆるLazyLoadで、一般的にはjQuery依存のLazyLoadライブラリが定番らしいが、調べるなかでjQueryに依存しないlazysizesライブラリの方が軽くて記述も簡単だったので、今回これを採用した。 https://wemo.tech/207

しかしサイト上部でslick.js(jQuery依存のスライドショーのライブラリ)を使用していたので、ファーストビューのスライド部分では上手く遅延読み込みがでませんでした。これはslick.jsに元々備わっている画像遅延機能を使ってsrc=””をlazy-data=””に置き換えることで解決した。

途中、echo.jsを使おうかとも思い試してみたが、lazysizesに比べて画像のカクツキ(スクロール時の読み込み開始タイミングやスピードの遅さ)がひどかったので、やはりlazysizesがベストだと思う。

追記(WordPressの場合)

WordPressであればLazyLoad by WP Rocketプラグインがおすすめ。他と比べてカスタムフィールドで出力した画像や関連記事のサムネイル画像などのあらゆる画像遅延ができ、ロード時のチラつきも気にならない。標準のthreshold(スクロールが画像の何ピクセル上まできたら画像読み込みを開始するかの閾値)の設定が綺麗なのだろう。

ただしファーストビューに入る画像のうち、本文以外のロゴやサイドバーの画像まで遅延させてしまうので、これらをdata-no-lazy=’1’の付与によって無効化しなければならないのが少しやっかい(functions.phpにてクラスの指定による除外フィルターの設定も出来るが、複数のクラスを指定する方法がどうにも分からなかったので1つずつimgタグに属性付与していくしか今のところ方法が分からない)。

レンダリングを妨げるリソースの除外

これはこれまでもあった「レンダリングブロックしている(HTMLの描画を妨げている)CSSやJavaScriptを後から読み込ませる」もの。

WordPressならAutoptimizeやScrpit To Footerプラグインなどで対応できるが、今回は静的なHTMLサイトなので<script>を</body>タグの直前に1こずつ手動で移動させた。

またjQuery以外のScriptには非同期かつ順序読み込みのdefer属性をつけて遅延させた(async属性だと同じ非同期でも読み込み順序が記述した順番通りになる保証はなく、それぞれのscriptが読み込み終わり次第バラバラに実行されて不具合の原因になる。しかしなぜかGoogleはasyncを推奨している)。

jQueryは重要なスクリプトライブラリ(Critical Request Chainとか言うらしい)なので、初めに呼ばないとナビメニューやスライドショーが動かなくなったりする。よってこれの読み込み部分はheadの中に留めておいた方が無難(つまりjQueryによるレンダリングブロックは諦める)。

一応<head></head>の中でなく</body>直前で呼べばエラーもなく、PSIの警告も消えるらしいが、そこで読んで不具合が本当に起きないかは慎重になるべきである。結局「jQueryを使ったJavaScript functionを使う時点で読み込まれているかどうかがポイントだ」という点を理解して、jQueryやdeferを使っているかという点が重要なんだと思う。

また全てのCSSの読み込みを遅くすると一瞬見た目が酷く崩れて表示されてしまう。UX上よくないので、ファーストビューに必要なCSSだけ<style>タグでインライン化して<head>の中に直に書き出す。

CSSとJavaScriptをインライン化する際はもちろん圧縮(改行やタブ、コメントを削除)する方がよく、これには便利なWebサービスがあるのでこちらを利用。 https://prettydiff.com/?m=beautify

追記

ファーストビューで使われているCSSが分からない場合、Chrome Developer Toolで要素選択して適用クラスを見ていくしかないかも。

「現在のページで使われているCSSの抽出」であれば、同じくChrome Developer ToolのCoverage機能(Toolのタブに見当たらなければ[…]をクリックしてでるMore Tool?の中に入っている)で洗い出せる(このCoverageの使い方も詳しい記事が少なかったのでコメントいただければ書きます)。

適切なサイズの画像

モバイルの場合は画面幅が大きいiPhoneXS Maxでも414px(414×896ポイント)なので、それ以上の大きさの画像はバイト数を無駄に使っていることになる。 https://qiita.com/TD3P/items/b3b754bde584abc98f44

これもMacでサイズを変更した(iPadも考慮し750pxの横幅とした)上で再度webp形式の画像に変換しアップロードし、事なきを得た。 こちらのリンクも参考になります。 https://pantograph.co.jp/blog/research/above-the-fold.html

追記(WordPressの場合)

WordPressであればバージョン4.4くらいからレスポンシブイメージと言って画像を挿入したときに画面サイズごとにw300のような属性?が割り当てられたimgタグが自動で用意・挿入されるようになり、基本はこのレスポンシブイメージ機能によりこの項目は自動でクリアされるはず。

しかしテーマによってはこれを無効にしていたり、上手く機能しない場合もあるようで、そう言った時は手動でリサイズするしかなさそう。

しかしこの時はPCとモバイルでページが分かれており、そのうちのモバイル専用ページだったので良かったが、PC/モバイル兼用のページだと414px以上の画像もPCで必要なので、どうやってやればいいんだろう…。@mediaとdisplayプロパティで出しわけとかするしかないのだろうか…。今一度、参考リンクや本で勉強し直す必要がありそうです。

キーリクエストのプリロード

これはGoogleの公式ドキュメントが分かりやすいが、要はjsなどを<link>で読み込んだ時、それらのコードの中でもcssファイルを読込み必要があると、HTML→親のjs→子のcssという順番で読み込まれて遅いので、HTMLの<head>の段階で明示的にpreloadを指定して、子のcssも事前に読み込んでおきましょうってことです。 https://developers.google.com/web/tools/lighthouse/audits/preload

ちなみに、色んなブログなどの情報をみて誤解しやすいのは、HTML(親)の<head>で元からある<link>にrel=”preload”をつけるんじゃなくて、その<link>で読んだファイル(子)で使うためのcssやjsファイル(孫)を、子から呼び出されるより先に親の段階で

<linkrel=”preload” as=”script” href=”child-script.js”>

のように記載して事前読み込しましょうってことですからね。

またフォントの場合は書き方が異なり、

<link rel=”preload” as=”font” type=”font/woff2″ href=”font.woff2″ crossorigin>

のように書くとのこと(ちなみにHTMLの記述ルールでは”(ダブルクォーテーション)はあってもなくてもいいみたいです)。 もろもろの参考はこちらです。 https://blog.jxck.io/entries/2016-03-04/preload.html

まとめ

上記で「改善できる項目」に出ていた警告は消えましたが、たまに「サーバーの応答時間が遅い(TTFB)」という項目がでて2秒くらい表示が遅れてると言われたり、他の「診断」などの項目が赤や黄色の警告のままなので、そこを改善しないと90以上のスコアを取るのは難しいようです。

続き:「診断編」へ

診断編も書きました。診断と言えど「静的なアセットと効率的なキャッシュポリシーの配信」などの項目でスコアは大きく変わるので、こちらもご参考ください。