PageSpeed のルールと推奨事項

公開日: 2018 年 8 月 17 日

このガイドでは、コンテキストに応じた PageSpeed Insights ルールについて、つまりクリティカル レンダリング パスを最適化する際の注意点と注意すべき理由を説明します。

レンダリングをブロックする JavaScript と CSS を排除する

最初のレンダリングまでの時間をできるだけ短縮するには、ページ上のクリティカル リソース数の最小化(可能な場合はリソースの除去)、ダウンロードするクリティカル バイト数の最小化、クリティカル パス長の最適化を行います。

JavaScript の使用を最適化する

JavaScript リソースは、async とマークされているか、特別な JavaScript スニペットを使用して追加されている場合を除き、デフォルトでパーサー ブロックです。パーサー ブロック JavaScript は、ブラウザを強制的に CSSOM で待機させ、DOM の構築を一時停止します。その結果、最初のレンダリングまでの時間が大幅に遅れる可能性があります。

非同期 JavaScript リソースを優先する

非同期リソースの場合、ドキュメント パーサーはブロックされず、ブラウザでは、スクリプトを実行する前の CSSOM ブロックを回避できます。多くの場合、スクリプトが async 属性を使用できるということは、最初のレンダリングに必須ではないことも意味します。最初のレンダリングの後、スクリプトを非同期で読み込むことを検討してください。

同期サーバー呼び出しを避ける

navigator.sendBeacon() メソッドを使用して、unload ハンドラで XMLHttpRequests によって送信されるデータを制限します。多くのブラウザでは、このようなリクエストの同期が求められるため、ページの遷移が著しく遅くなる可能性があります。次のコードは、navigator.sendBeacon() を使用して、unload ハンドラではなく pagehide ハンドラでサーバーにデータを送信する方法を示しています。

<script>
  function() {
    window.addEventListener('pagehide', logData, false);
    function logData() {
      navigator.sendBeacon(
        'https://putsreq.herokuapp.com/Dt7t2QzUkG18aDTMMcop',
        'Sent by a beacon!');
    }
  }();
</script>

データを非同期でリクエストする場合、fetch() メソッドの方が適しています。fetch() は、複数のイベント ハンドラではなく Promise を使用してレスポンスを処理します。XMLHttpRequest に対するレスポンスとは異なり、fetch() レスポンスはストリーム オブジェクトです。つまり、json() を呼び出すと Promise も返ります。

<script>
  fetch('./api/some.json')
    .then(
      function(response) {
        if (response.status !== 200) {
          console.log('Looks like there was a problem. Status Code: ' +  response.status);
          return;
        }
        // Examine the text in the response
        response.json().then(function(data) {
          console.log(data);
        });
      }
    )
    .catch(function(err) {
      console.log('Fetch Error :-S', err);
    });
</script>

fetch() メソッドでは、POST リクエストも処理できます。

<script>
  fetch(url, {
    method: 'post',
    headers: {
      "Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
    },
    body: 'foo=bar&lorem=ipsum'
  }).then(function() { // Additional code });
</script>

JavaScript の解析を延期する

ブラウザがページのレンダリングのために実行する作業量を最小化するには、最初のレンダリングで表示コンテンツを構築するために必須ではないスクリプトは処理を延期して、ページをレンダリングするためにブラウザで実行しなければならない作業量を最小化する必要があります。

長時間実行される JavaScript を避ける

長時間実行される JavaScript があると、ブラウザによる DOM の構築、CSSOM の構築、ページ レンダリングがブロックされます。そのため、最初のレンダリングで必須ではない初期化ロジックは、レンダリング後まで処理を延期する必要があります。長い初期化シーケンスを実行する必要がある場合は、ブラウザが間に他のイベントを処理できるように、複数のステージに分割することを検討してください。

CSS の使用法を最適化する

CSS は、レンダリング ツリーの構築に必要であり、通常 JavaScript は、最初にページを構築する際に CSS でブロックをします。重要でない CSS(print その他のメディアクエリなど)はすべて非クリティカルとして指定し、クリティカル CSS の量とその配信時間をできる限り削減する必要があります。

CSS をドキュメント ヘッドに含める

すべての CSS リソースを HTML ドキュメント内でできるだけ早く指定すると、ブラウザで <link> タグを検出して CSS のリクエストをディスパッチするまでの時間を短縮することができます。

CSS のインポートを避ける

CSS のインポート(@import)ディレクティブを使用すると、あるスタイルシート ファイルから別のスタイルシートにルールをインポートできます。ただし、このディレクティブは、クリティカル パスにラウンドトリップを追加することになるため、避ける必要があります。インポートされる CSS リソースは、@import ルールのある CSS スタイルシート自体の取得と解析が完了した後でようやく検出されます。

レンダリングをブロックする CSS をインライン化する

最大のパフォーマンスを得るには、クリティカル CSS を、HTML ドキュメントに直接インライン化することをおすすめします。これにより、クリティカル パスから余計なラウンドトリップを排除できます。また、適切に実施すれば、HTML 以外のブロック リソースがない「1 ラウンドトリップ」のクリティカル パス長を実現できます。

フィードバック