この 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.js
とpublic/style.391484cf.css
は、ウェブアプリの JavaScript アセットと CSS アセットです。これらのファイルには、コンテンツに対応するハッシュが URL に含まれています。index.html
は、どのバージョニングされた URL を読み込むかを管理します。
HTML のキャッシュ ヘッダーを構成する
バージョニング情報を含まない URL へのリクエストに応答する場合は、レスポンス メッセージに Cache-Control: no-cache
を追加してください。また、2 つの追加レスポンス ヘッダー(Last-Modified
または ETag
)のいずれかを設定することをおすすめします。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.js
と style.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 の [ネットワーク] パネルを開いてライブアプリをプレビューし、適切なヘッダーが設定されていることを確認できます。
サイトをプレビューするには、[アプリを表示] を押してから、全画面表示 を押します。
列ヘッダーを右クリックして、最も関連性の高い情報が含まれるように [Network] パネルに表示される列をカスタマイズします。
ここで注目すべき列は、Name
、Status
、Cache-Control
、ETag
、Last-Modified
です。
- DevTools で [Network] パネルが開いた状態で、ページを更新します。
ページが読み込まれると、[Network] パネルに次のようなエントリが表示されます。
最初の行は、移動先の HTML ドキュメントの行です。これは Cache-Control: no-cache
で適切に処理されます。そのリクエストの HTTP レスポンス ステータスは 304
です。つまり、ブラウザはキャッシュ内の HTML をすぐには使用せず、代わりに Last-Modified
と ETag
の情報を使用して、ウェブサーバーに HTTP リクエストを行い、キャッシュにすでにある HTML に更新があるかどうかを確認します。HTTP 304 レスポンスは、更新された HTML がないことを示します。
次の 2 行は、バージョニングされた JavaScript アセットと CSS アセット用です。Cache-Control: max-age=31536000
とともに提供され、それぞれの HTTP ステータスは 200
になります。使用されている構成のため、Node.js サーバーに対して実際にリクエストが行われることはありません。エントリをクリックすると、レスポンスが「(ディスク キャッシュから)」という内容など、詳細が表示されます。
ETag 列と Last-Modified 列の実際の値はあまり重要ではありません。重要なのは、これらが設定されていることを確認することです。
まとめ
この Codelab の手順を完了したところで、HTTP キャッシュを適切に使用するために、Express を使用して Node.js ベースのウェブサーバーで HTTP レスポンス ヘッダーを構成する方法を理解できました。また、Chrome の DevTools の [Network] パネルで、期待されるキャッシュ動作が使用されていることを確認する手順も用意されています。