HTTPキャッシュ入門:基本から応用まで
HTTPキャッシュとは
HTTPキャッシュは、サーバーの負荷を軽減し、クライアントの応答時間を短縮し、ネットワーク帯域幅を節約することで、Webパフォーマンスを向上させる技術です。HTTPキャッシュには、強制キャッシュと協調キャッシュの2種類があります。
強制キャッシュ
強制キャッシュでは、クライアントが指定された期間内にローカルにキャッシュされたリソースを直接使用できるようにします。この場合、サーバーへのリクエストを送信する必要はありません。強制キャッシュは、サーバーによって指定されるレスポンスヘッダー、主にCache-ControlとExpiresフィールドによって制御されます。
Cache-Control
Cache-Controlは、最大有効期間(`max-age`)、キャッシュの共有可否(`public`または`private`)、および変更の許可可否(`no-cache`または`no-store`)を指定する汎用ヘッダーです。
例:
Cache-Control: max-age=3600
上記は、リソースが3600秒間有効であり、キャッシュ可能であることを示しています。
Expires
Expiresは、キャッシュの有効期限を絶対的な時間で指定する廃止予定のフィールドです。
例:
Expires: Wed, 23 Aug 2024 03:36:26 GMT
これは、リソースが2024年8月23日午前3時36分26秒に期限切れになることを意味します。
Cache-ControlとExpiresの両方が存在する場合は、Cache-Controlが優先されます。
協調キャッシュ
協調キャッシュでは、クライアントがリソースが更新されているかどうかをサーバーに確認する必要があります。更新されていない場合、サーバーは`304`ステータスコードと空のレスポンスボディを返し、クライアントはローカルキャッシュを引き続き使用できます。更新されている場合、サーバーは`200`ステータスコードと新しいリソースを返し、ローカルキャッシュを置き換えます。協調キャッシュは、主にLast-Modified/If-Modified-SinceとETag/If-None-Matchヘッダーを利用します。
Last-Modified/If-Modified-Since
Last-Modifiedは、リソースの最終更新時刻を示すサーバー側のフィールドです。
例:
Last-Modified: Tue, 22 Aug 2024 02:36:26 GMT
これは、リソースが2024年8月22日午前2時36分26秒に最終更新されたことを示しています。
If-Modified-Sinceは、リソースを最後に取得した時刻を示すクライアント側のフィールドです。
例:
If-Modified-Since: Tue, 22 Aug 2024 02:36:26 GMT
これは、クライアントがリソースを2024年8月22日午前2時36分26秒に取得したことを示しています。
両方のタイムスタンプが等しい、またはLast-Modifiedがより古い場合、リソースは更新されていません。Last-Modifiedが後の場合、リソースは更新されています。
ETag/If-None-Match
ETagは、リソースの一意の識別子を表すサーバー側のフィールドです。
例:
ETag: '5d3a9f6d-1f86'
これは、リソースの識別子が`"5d3a9f6d-1f86"`であることを示しています。
If-None-Matchは、リソースの期待される識別子を示すクライアント側のフィールドです。
例:
If-None-Match: '5d3a9f6d-1f86'
これは、クライアントがリソース識別子として`"5d3a9f6d-1f86"`を期待していることを示しています。
両方の値が一致する場合、リソースは更新されていません。不一致の場合、リソースは更新されています。
HTTPキャッシュのベストプラクティス
協調キャッシュと強制キャッシュを組み合わせることで、不要なネットワークリクエストを効果的に削減しつつ、常に最新のコンテンツをユーザーに提供できます。
一般的なアプローチ:
強制キャッシュ:CSSやJS、画像などの静的リソースには長いキャッシュ期間を設定します。これにより、ブラウザはサーバーに問い合わせることなくローカルストレージからリソースを直接取得できます。
協調キャッシュ:変更される可能性のあるリソースには協調キャッシュを使用します。ブラウザはリソースが変更されたかどうかをサーバーに確認します。変更されていない場合、サーバーは`304 Not Modified`レスポンスを返し、ブラウザはローカルキャッシュを使用します。リソースが変更された場合、サーバーは`200 OK`と更新されたリソースを返します。
実装例:
Express.jsをバックエンドフレームワークとして使用する場合:
const express = require('express');
const app = express();
// 強制キャッシュ:静的リソースにキャッシュを設定
app.use(
'/static',
express.static('public', {
maxAge: '1y', // キャッシュ期間は1年
})
);
// 協調キャッシュ:ETagとLast-Modifiedを使用
app.get('/resource', (req, res) => {
const content = '...'; // リソースの内容を取得
const etag = generateETag(content); // ETagを生成
// If-None-Matchヘッダーを確認
if (req.headers['if-none-match'] === etag) {
res.status(304).end(); // リソースが変更されていない場合、304を返す
} else {
res.setHeader('ETag', etag);
res.send(content); // リソースが変更されている場合、新しい内容を返す
}
});
function generateETag(content) {
return require('crypto').createHash('md5').update(content).digest('hex');
}
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
注意事項
バージョン管理:強制キャッシュの効果を最大化するために、リソースURLにバージョン情報を含めます。例:`/static/js/main.2024082301.js`。リソースを更新する際には、バージョン番号を変更して、ユーザーが常に最新バージョンを取得できるようにします。
協調キャッシュのコスト:協調キャッシュは不要なデータ転送を削減しますが、ネットワークの往復が必要です。ほとんど変更されないリソースには、強制キャッシュのほうが効率的な場合があります。
私たちはLeapcell、バックエンド・プロジェクトのホスティングの最適解です
Leapcellは、Webホスティング、非同期タスク、Redis向けの次世代サーバーレスプラットフォームです:
複数言語サポート
Node.js、Python、Go、Rustで開発できます。
無制限のプロジェクトデプロイ
使用量に応じて料金を支払い、リクエストがなければ料金は発生しません。
比類のないコスト効率
使用量に応じた支払い、アイドル時間は課金されません。
例: $25で6.94Mリクエスト、平均応答時間60ms。
洗練された開発者体験
直感的なUIで簡単に設定できます。
完全自動化されたCI/CDパイプラインとGitOps統合。
実行可能なインサイトのためのリアルタイムのメトリクスとログ。
簡単なスケーラビリティと高パフォーマンス
高い同時実行性を容易に処理するためのオートスケーリング。
ゼロ運用オーバーヘッド — 構築に集中できます。
Xでフォローする:@LeapcellHQ