blog.comame.xyz

TL;DR

  1. レンダリングブロッキング要素を減らす
    1. <script>
    2. <link rel="stylesheet">
  2. Web フォントのロードを制御する
  3. 画像を最適化する
  4. 地理的に近い場所にサーバを置く

レンダリングブロッキング要素を減らす

ブラウザのレンダラは、HTML を上から順に (ファイルに記述してある順に) 解釈して DOM を構築します。途中で JavaScript や CSS が埋め込まれている場合は、スクリプトの実行やスタイルの計算が終わるまで DOM の構築は中断されます。これをレンダリングブロッキングと呼びます。

<script>

最も効果的な対処法は、async 属性をつけることです。async 属性が付与されたスクリプトは、DOM の構築を妨げません。特に、外部リソースを取得するような場合に効果が発揮されます。一方で、複数の <script> タグにそれぞれ async 属性が付与されていた場合、実行順序が保証されないことに注意が必要です。HTMLScriptElement.onload イベントを活用するのが良いでしょう。

<link rel="stylesheet">

<script> タグの場合は async 属性をつけるだけで済みましたね。しかし、<link> タグには非同期に読み込ませるような属性は存在しません。そのため、JavaScript を使用して非同期に読み込ませるような処理を書くことになります。

<head>
  <noscript id="async-styles">
  <link rel="stylesheet" href="style.css">
  </noscript>
  <script>
  window.requestAnimationFrame(() => {
    document.head.innerHTML +=
    document.getElementById('async-styles').textContent;
  });
  </script>
</head>

あるいは、<style> タグを使用して HTML に埋め込んでしまうのも有効です。ただし、再利用性が低いこと、Contents Security Policy との相性が悪いことに注意が必要です。

実際のところ、レンダリングブロックする要素を減らすだけでも相当な効果が見込めます。適切にレンダリングブロックを制御した場合、リソースのダウンロードがすべて完了していなくとも必要最低限の要素だけ表示させることができます。

一方で、JavaScript の実行が必須な Web アプリケーションの場合、表示されているのに操作できない時間が発生することになります。このような場合は、ローディングアニメーションを表示するか、あるいは意図的にレンダリングブロックを発生させるという手段も選択肢となり得るでしょう。

Web フォントのロードを制御する

Web フォントというのはとても便利なものです。導入が簡単にもかかわらず、Web ページの印象を大きく変えてくれます。

しかし、無頓着に Web フォントを使うのは考えものです。ネットワークの速度が遅い環境では、Web フォントのロードが終わるまで文字が表示されないかもしれません。(みなさんも経験ありませんか?) 酷い場合にはユーザーを5秒以上待たせてしまうこともあります。

これは CSS ファイルにほんの数行付け足すだけで解決できます。

@font-face {
  /* ... */
  font-display: swap;
}

この 1 行を付け足すだけで、ブラウザは Web フォントがロードされるまでは、オフラインで使用可能な他のフォントで代わりに表示してくれます!

画像を最適化する

Web ページの平均サイズはどんどん巨大化しています。そして、そのうちの大部分を画像が占めています。画像のファイルサイズを少しでも減らすことができれば、きっともう少しページの読み込みが早くなることでしょう。

WebP など最新のフォーマットを有効活用しましょう。フォーマットに気を配るだけで、ファイルサイズを大幅に削減できます。

<picture> タグを使って複数のフォーマットの画像を選択できるようにすれば、最新のフォーマットに対応していないようなブラウザでも正常に画像を表示させることができます。

最後に>

これらの対策を施したら、最適化の効果の程を確かめてみましょう。Chrome ブラウザを使用しているのであれば、DevTools の Audits タブでパフォーマンスを調査できます。

また、PageSpeed Insights を使用するのもおすすめです。

ここに紹介した以外にもたくさんの高速化の手法があります。調べてみると良いでしょう。

  • Resource Hints
  • Service Worker + Cache API
  • Lazy Load (Intersection Observer v2 とかいい感じに使えそう)
  • レイアウトを静的に指定する
  • AMP (Accelerated Mobile Pages)
  • SSR (Server Side Rendering)

2019/07/04 追記

上にメモした Lazy Loading ですが、Chrome に loading 属性が追加されました。まだ実用段階ではなさそうですが、注目していきたいです。

2019/07/10 また追記

今まで Google Compute Engine の US リージョンに置いていましたが、ConoHa の東京リージョンに置くようにしたらめちゃくちゃ速度が改善しました。地理的な要因も見過ごせませんね。