HTTP キャッシュ動作の構成

この Codelab では、Express サービング フレームワークを実行する Node.js ベースのウェブサーバーから返される HTTP キャッシュ ヘッダーを変更する方法について説明します。また、Chrome の DevTools の [Network] パネルを使用して、想定どおりのキャッシュ処理が実際に適用されていることを確認する方法についても説明します。

サンプル プロジェクトに慣れる

サンプル プロジェクトで使用する主なファイルは次のとおりです。

  • server.js には、ウェブアプリのコンテンツを提供する Node.js コードが含まれています。Express を使用して HTTP リクエストとレスポンスを処理します。特に、express.static() は公開ディレクトリ内のすべてのローカル ファイルを提供するために使用されるため、serve-staticドキュメントが役に立ちます。
  • public/index.html はウェブアプリの HTML です。ほとんどの HTML ファイルと同様に、URL の一部としてバージョニング情報は含まれません。
  • public/app.15261a07.jspublic/style.391484cf.css は、ウェブアプリの JavaScript アセットと CSS アセットです。これらのファイルには、それぞれ内容に対応するハッシュが URL に含まれています。index.html は、読み込む特定のバージョニングされた URL を追跡します。

HTML のキャッシュ ヘッダーを構成する

バージョニング情報のない URL のリクエストに応答する場合は、レスポンス メッセージに Cache-Control: no-cache を追加してください。また、Last-Modified または ETag の 2 つのレスポンス ヘッダーのいずれかを設定することをおすすめします。index.html はこのカテゴリに該当します。この作業は 2 つのステップに分けることができます。

まず、Last-Modified ヘッダーと ETag ヘッダーは、etag 構成オプションと lastModified 構成オプションによって制御されます。これらのオプションは、実際にはすべての HTTP レスポンスでデフォルトで true に設定されているため、現在の設定では、この動作を有効にする必要はありません。ただし、明示的に設定することもできます。

次に、Cache-Control: no-cache ヘッダーを追加する必要がありますが、これは HTML ドキュメント(この場合は index.html)に限られます。このヘッダーを条件付きで設定する最も簡単な方法は、カスタム setHeaders function を作成し、その中で受信したリクエストが HTML ドキュメントかどうかを確認することです。

  • [Remix to Edit] をクリックして、プロジェクトを編集可能にします。

server.js の静的サービング構成は、次のように開始されます。

app.use(express.static('public'));
  • 上記の変更を行うと、次のようなコードになります。
app.use(express.static('public', {
  etag: true, // Just being explicit about the default.
  lastModified: true,  // Just being explicit about the default.
  setHeaders: (res, path) => {
    if (path.endsWith('.html')) {
      // All of the project's HTML files end in .html
      res.setHeader('Cache-Control', 'no-cache');
    }
  },
}));

バージョニングされた URL のキャッシュ ヘッダーを構成する

フィンガープリント」またはバージョニング情報が含まれ、コンテンツが変更されることのない URL のリクエストに応答する場合は、レスポンスに Cache-Control: max-age=31536000 を追加します。app.15261a07.jsstyle.391484cf.css はこのカテゴリに該当します。

前回のステップで使用した setHeaders function を基に、追加のロジックを追加して、特定のリクエストがバージョニングされた URL かどうかを確認し、バージョニングされている場合は Cache-Control: max-age=31536000 ヘッダーを追加できます。

最も堅牢な方法は、正規表現を使用して、リクエストされたアセットがハッシュが該当する特定のパターンと一致するかどうかを確認することです。このサンプル プロジェクトの場合、常に 0 ~ 9 の数字と a ~ f の小文字のセットから 8 文字(16 進数文字)になります。ハッシュは常に両側が . 文字で区切られています。

これらの一般的なルールに一致する正規表現は new RegExp('\\.[0-9a-f]{8}\\.') で表すことができます。

  • setHeaders 関数を次のように変更します。
app.use(express.static('public', {
  etag: true, // Just being explicit about the default.
  lastModified: true,  // Just being explicit about the default.
  setHeaders: (res, path) => {
    const hashRegExp = new RegExp('\\.[0-9a-f]{8}\\.');

    if (path.endsWith('.html')) {
      // All of the project's HTML files end in .html
      res.setHeader('Cache-Control', 'no-cache');
    } else if (hashRegExp.test(path)) {
      // If the RegExp matched, then we have a versioned URL.
      res.setHeader('Cache-Control', 'max-age=31536000');
    }
  },
}));

DevTools を使用して新しい動作を確認する

静的ファイル サーバーを変更したら、DevTools の [ネットワーク] パネルを開いてライブアプリをプレビューし、正しいヘッダーが設定されていることを確認します。

  • サイトをプレビューするには、[アプリを表示] を押してから、[全画面表示] 全画面表示 を押します。

  • 列見出しを右クリックして、ネットワーク パネルに表示される列をカスタマイズし、最も関連性の高い情報を含めます。

DevTools の [ネットワーク] パネルの構成。

ここで注意すべき列は、NameStatusCache-ControlETagLast-Modified です。

  • DevTools の [ネットワーク] パネルを開いた状態で、ページを更新します。

ページが読み込まれると、[ネットワーク] パネルに次のようなエントリが表示されます。

ネットワーク パネルの列。

最初の行は、移動した HTML ドキュメント用です。これは Cache-Control: no-cache で適切に提供されます。そのリクエストの HTTP レスポンス ステータスは 304 です。これは、ブラウザがキャッシュに保存されている HTML をすぐに使用しないことを認識し、代わりに Last-ModifiedETag の情報を使用して、キャッシュにすでに保存されている HTML が更新されていないかどうかを確認するために、ウェブサーバーに HTTP リクエストを送信したことを意味します。HTTP 304 レスポンスは、更新された HTML がないことを示します。

次の 2 行は、バージョニングされた JavaScript アセットと CSS アセット用です。Cache-Control: max-age=31536000 で提供され、各 HTTP ステータスが 200 になっているはずです。使用されている構成により、Node.js サーバーに実際のリクエストは送信されません。エントリをクリックすると、「(ディスク キャッシュから)」などのレスポンスの詳細が表示されます。

ネットワーク レスポンス ステータスが 200 の場合。

ETag 列と Last-Modified 列の実際の値は重要ではありません。重要なのは、設定されていることを確認することです。

まとめ

この Codelab の手順を完了すると、HTTP キャッシュを最適に使用するために、Express を使用して Node.js ベースのウェブサーバーで HTTP レスポンス ヘッダーを構成する方法について理解しているはずです。また、Chrome の DevTools の [Network] パネルを使用して、想定どおりのキャッシュ動作が使用されていることを確認する手順もあります。