フロントエンドのキャッシュについて

# HTTP キャッシュ
過去に取得したリソースを再使用すると、ウェブサイトやアプリケーションのパフォーマンスが大きく向上するでしょう。ウェブキャッシュは遅延やネットワークのトラフィックを削減して、リソースを表示するために必要な時間も短縮します。HTTP キャッシュを使用すると、ウェブサイトの応答性が高まります。

---

# キャッシュの基本

---

## キャッシュしない
```
Cache-Control: no-store
```

---

## キャッシュを検証する
キャッシュした複製を渡す前に検証のため、キャッシュは生成元のサーバーにリクエストを送信します
```
Cache-Control: no-cache
```
または

```
Cache-Control: max-age=0, must-revalidate
```

---

## 有効期限
設定期間が過ぎたら、サーバーにリクエストして、リソースをダウンロードします。
```
Cache-Control: max-age=31536000
```

---

# キャッシュの検証

```
Cache-Control: must-revalidate
```

---

## Last-Modified/If-Modified-Since
リソースのレスポンスのheaderに`Last-Modified`がもらえる
```
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
Last-Modified: Tue, 22 Feb 2022 22:00:00 GMT
Cache-Control: max-age=3600

<!doctype html>
…

```

3600秒に過ぎたら、リソースをまたリクエストして、`If-Modified-Since` を設定します。

```
GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
If-Modified-Since: Tue, 22 Feb 2022 22:00:00 GMT

```

もしリソースは新しくにならなければ、304返して、フロントエンドの方はキャッシュしているリソースを使います。
```
HTTP/1.1 304 Not Modified
Content-Type: text/html
Date: Tue, 22 Feb 2022 23:22:22 GMT
Last-Modified: Tue, 22 Feb 2022 22:00:00 GMT
Cache-Control: max-age=3600
```

---

## ETag/If-None-Match

リソースのレスポンスのheaderに`ETag`がもらえる
```
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
ETag: "33a64df5"
Cache-Control: max-age=3600

<!doctype html>
…


```

3600秒に過ぎたら、リソースをまたリクエストして、`IIf-None-Match` を設定します。

```
GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
If-None-Match: "33a64df5"

```

もしリソースは新しくにならなければ、304返して、フロントエンドの方はキャッシュしているリソースを使います。
```
HTTP/1.1 304 Not Modified
Content-Type: text/html
Date: Tue, 22 Feb 2022 23:22:22 GMT
Last-Modified: Tue, 22 Feb 2022 22:00:00 GMT
ETag: "33a64df5"
Cache-Control: max-age=3600
```

---

# フロントエンドエンジニアはキャッシュのことはあまり気にしなかった　→　なぜ
## デフォルトキャッシュStragegyがあります: Heuristic caching

## Js Bundle
- Webpack
- Vite

## Webフレームワーク対応してくれます
- Rails 
- Laravel 


## Webサーバー対応してくれます。
- Cloudfront
- CDN

---

## リソースのレスポンスHeaderにキャッシュの設定はなにもない場合、クライアントは自分で判断します。

```

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
Last-Modified: Tue, 22 Feb 2021 22:22:22 GMT

<!doctype html>
…

```


## エンジニアは何もしなくてもキャッシュしてくれます。

---

# Commonのキャッシュ方法
---

## キャッシュしたくない場合、

```
Cache-Control: no-cache, no-store, must-revalidate
```

- 例: APIのリクエスト
- 例: index.htmlファイル

---

## リソースを変更するときに、リソースパースを変更します。

```
# version in filename
bundle.v123.js

# version in query
bundle.js?v=123

# hash in filename
bundle.YsAIAAAA-QG4G6kCMAMBAAAAAAAoK.js

# hash in query
bundle.js?v=YsAIAAAA-QG4G6kCMAMBAAAAAAAoK

```

- リソースパスが変わったら、クライアントはリクエストを送信して、リソースをダウンロードします。
- フロントエンドのJsビルドライブラリーにはあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318767/8da488dd-53fb-1bb3-240c-761a99757339.png)


---

## 実際に画像はキャッシュしてくれない問題があります。

### S3のpresigned urlを使います。
- S3のpresigned urlは毎回に変わるため、クライアントは毎回にリクエストを送信して画像をダウンロードします。
- 対策は: バックエンドで画像ごとに画像リンクを固定します。バックエンドでS3のpresigned urlにredirectします。

### バックエンドで画像リンクがありますが、キャッシュの設定は`no-cache, no-store, must-revalidate`でした。
- バックエンドのAPIはデフォルトのヘッダーの設定はキャッシュしないため、画像リンクが変わらなくても毎回にリクエストを送信します。
- 対策は画像のリンクのヘッダーはキャッシュしない設定を外します。

---