見出し画像

HTTPキャッシュ入門:基本から応用まで

HTTPキャッシュとは

HTTPキャッシュは、サーバーの負荷を軽減し、クライアントの応答時間を短縮し、ネットワーク帯域幅を節約することで、Webパフォーマンスを向上させる技術です。HTTPキャッシュには、強制キャッシュ協調キャッシュの2種類があります。

強制キャッシュ

強制キャッシュでは、クライアントが指定された期間内にローカルにキャッシュされたリソースを直接使用できるようにします。この場合、サーバーへのリクエストを送信する必要はありません。強制キャッシュは、サーバーによって指定されるレスポンスヘッダー、主にCache-ControlExpiresフィールドによって制御されます。

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-ControlExpiresの両方が存在する場合は、Cache-Controlが優先されます。

協調キャッシュ

協調キャッシュでは、クライアントがリソースが更新されているかどうかをサーバーに確認する必要があります。更新されていない場合、サーバーは`304`ステータスコードと空のレスポンスボディを返し、クライアントはローカルキャッシュを引き続き使用できます。更新されている場合、サーバーは`200`ステータスコードと新しいリソースを返し、ローカルキャッシュを置き換えます。協調キャッシュは、主にLast-Modified/If-Modified-SinceETag/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


ブログでこの記事を読む

いいなと思ったら応援しよう!