ブラウザのキャッシュについて知っておくべきこと

ブラウザのキャッシュ

キャッシュの原則は、最初のリクエストの後にリクエストされたリソースの応答のコピーを保存することです。ユーザーが同じリクエストを再度開始すると、キャッシュがヒットすると、以前に保存されたコピーがブラウザに直接返され、再開始を回避します。サーバーへのリソース要求。

image.pngHTTPキャッシングは、私たちの日常の開発で最も一般的に使用されているキャッシングテクノロジーです。HTTPキャッシュは、キャッシュヒットを判断するときに、ブラウザがサーバーへの要求を開始してキャッシュ関連情報について問い合わせる必要があるかどうかに応じて、強力なキャッシュとネゴシエーションキャッシュに分けることができます。

強力なキャッシュ

キャッシング戦略は、HTTPヘッダーを設定することで実装されます。強力なキャッシングに関連するヘッダーフィールドは、Expiresとcache-controlです。

Expiresは、HTTP1.0プロトコルのキャッシュの有効期限とタイムスタンプを制御するフィールドです。これは絶対時間です。クライアントの現地時間がExpires時間を超えると、キャッシュの有効期限が切れることを意味します。

Expires: Mon, 21 Apr 2031 01:13:16 GMT
复制代码

Cache-Controlは、HTTP1.1プロトコルのキャッシュを制御するフィールドです。Cache-Controlのmax-age属性は、リソースキャッシュの有効期間(秒単位の時間)を制御します。315360000秒間有効です。

Cache-Control: max-age=315360000
复制代码

Cache-Controlは、キャッシュを制御するために他のいくつかのプロパティ値を構成することもできます:

  • no-store:キャッシュ戦略を使用することは禁止されており、すべてのリクエストはサーバーに送信されて最新のリソースを取得します。
  • キャッシュなし:リクエストが開始されるたびに、強力なキャッシュの有効期限チェックに直接入るのではなく、サーバーと直接ネゴシエートしてローカルキャッシュの有効性を確認します。つまり、ネゴシエートされたキャッシュルートを使用して話し合います。下。
  • private:リソースは、ブラウザによってのみキャッシュできます。これは、Cache-Controlのデフォルト値です。
  • must-revalidate:キャッシュ可能ですが、サーバーで再検証する必要があります。

(プロキシサーバーキャッシュの設定は以下のとおりです)

  • public:リソースはブラウザとプロキシサーバーの両方でキャッシュできます。
  • s-maxage:プロキシサーバーのキャッシュの有効期限。
  • proxy-revalidate:キャッシュされた応答を再検証するようにプロキシサーバーに要求します。

HTTP 1.1では、Cache-ControlはExpiresの完全な代替品です。一般的に、プロジェクトの実践で使用するだけで十分です。HTTP1.0との互換性のために、引き続きExpiresを使用してください。

キャッシュをネゴシエートする

当 Cache-Control 校验缓存过期,或者设置了no-cache时,浏览器就会与服务器进行协商,判断是重新发起请求、下载完整的响应,还是从本地获取缓存的资源。

跟协商缓存相关的 Header 字段有Last-Modified / If-Modified-SinceETag / If-None-Match (分别成对出现)

Last-Modified / If-Modified-Since

在每次服务器返回资源的同时,会在响应头中同时返回Last-Modified字段,它是一个时间戳,表示资源最近一次的修改时间。

last-modified: Mon, 11 Jan 2021 08:15:02 GMT
复制代码

随后我们每次需要发送请求时,会带上一个叫 If-Modified-Since 的时间戳字段,它的值就是上一次 response 返回的 Last-Modified 值。

if-modified-since: Mon, 11 Jan 2021 08:15:02 GMT
复制代码

服务器接收到这个时间戳后,会比对该时间戳和资源在服务器上的最后修改时间:

  • 如果两者不同,返回200和完整的响应内容。
  • 如果两者相同,返回304和空的响应体,直接从缓存读取资源。

需要注意的是,强缓存命中对应的状态码是200,协商缓存命中对应的状态码是304。

ETag / If-None-Match

Etag 是由服务器为每个资源生成的唯一的标识字符串,类似于文件指纹。和 Last-Modified 类似,当首次请求时,会在响应头返回Etag字段。

etag: "88158AFCFF1E7F4B8B00A1BA81171B61"
复制代码

下一次请求时,会将之前响应头中Etag的值作为此次请求头中If-None-Match字段,提供给服务器进行校验。 若资源没有更新,就返回304和空的响应体,直接从缓存读取资源。否则,就会返回返回更新后的资源并且将新的缓存信息一起返回。

Etag 在感知文件变化上比 Last-Modified 更加准确,优先级也更高。当 Etag 和 Last-Modified 同时存在时,以 Etag 为准。

应用场景

html文档一般会设置 no-cache。在meta中设置:

<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="cache-Control" content="max-age=0">
复制代码

CSS,JS,图片等静态文件一般使用强缓存,设置较长的过期时间,并且文件名添加hash。比如掘金的文章详情页,js文件的缓存过期时间为max-age=31536000(一年)。

image.png

同时文件名必须添加hash,这样当文件名hash发生变化,则视为新的资源,从服务端直接获取。这样可以减少大量的静态资源的网络请求,由新hash标志的文件也不会因为缓存的原因滞后。

通过webpack,我们可以方便地为文件名添加hash。

用webpack为文件名添加hash

文件指纹是一串哈希符,通常是加载文件名后面,用于标识文件,做版本的管理。比如项目上线后,需要修改一些东西,只需要发布修改过的文件,对于没有修改过的文件,用户在访问的时候,依旧可以使用浏览器缓存,加速页面渲染。

webpack中的文件指纹有三种:

  • hash:和整个项目的构建相关,所有文件共用一个hash值,任何文件有修改,项目的hash值就会更改,没有实现缓存的效果。
  • chunkhash:根据不同的入口文件(entry)进行依赖文件解析、构建对应的chunk,生成对应的chunkhash值
  • contenthash: 由文件内容产生的hash值,内容不同产生的contenthash值也不一样。

设置文件指纹的通常是静态资源文件,以下是几种文件的文件指纹设置方法:

  • js:设置output的filename,使用[chunkhash]
output: {
   path: path.join(__dirname,"/dist"),
   filename: "js/bundle.[chunkhash:6].js"
}
复制代码
  • css:只有将css抽离成单独的文件时才需要设置指纹,借助mini-css-extract-plugin将css提取成独立的文件,设置mini-css-extract-plugin的filename。使用[contenthash],如果只修改js就可以不用重新上传css文件。
new MiniCssExtractPlugin({
    filename: 'css/[name].[contenthash:7].css'
})
复制代码
  • 图片:设置file-loader或url-loader的name,使用[hash],与上面整个项目构建的hash不同,图片等媒体文件的hash是根据文件的内容所生成的,换成[contenthash]也可以。
{
    test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
    loader: 'file-loader', 
    options: {
    	esModule: false,
        name: 'img/[name].[hash:7].[ext]'
    }
}
复制代码

ホットアップデートを使用する場合、chunkhashまたはcontenthashは使用できず、エラーが報告され、ハッシュのみが使用できます。したがって、ファイルフィンガープリントは通常、開発環境では設定されませんが、実稼働環境で設定されます。

おすすめ

転載: juejin.im/post/7084864717147078663