缓存过程分析
浏览器在第一次请求服务端时,服务端返回文件并设置缓存标识(比如,cache-control、expires、Etag等),等浏览器下一次请求相同的文件时(即url完全一致),会根据缓存的标识去判断,是直接使用浏览器缓存还是从服务端去拿。
一句话总结: 资源加载是否使用缓存,都是浏览器的事。** 是浏览器根据缓存标识来决定的。** 所以理解这些不同的缓存标识就很有必要了。
强缓存
缓存标识
缓存标识主要是cache-control、expires、Etag、Last-Modified / If-Modified-Since和Etag / If-None-Match 等
cache-control
在HTTP/1.1中,Cache-Control是最重要的规则,权重最大,主要用于控制网页缓存,主要取值为:
- public:所有内容都将被缓存(客户端和代理服务器都可缓存)
- private:所有内容只有客户端可以缓存,Cache-Control的默认取值
- no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定
- no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存
- max-age=xxx (sec):缓存内容将在Date之后xxx秒失效
expires
Expires是HTTP/1.0控制网页缓存的字段,其值为服务器返回该请求结果缓存的到期时间,即再次发起该请求时,如果客户端的时间小于Expires的值时,直接使用缓存结果。
形式是Expires: Wed, 21 Oct 2023 07:28:00 GMT
。但它使用的是本地时间,所以不太靠谱。
现在一般使用max-age来代替。 当两者都有时,max-age权重高于expires。
强缓存过程
- 浏览器第一次访问资源时,发现没有缓存。由服务端返回资源,并且添加缓存标识为
cache-control:max-age=60
。 - 浏览器60s内再访问资源时,发现时间没过期,直接从浏览器缓存读取。
- 浏览器60s后再访问,缓存过期了,得重新访问服务端去获取资源,并重复步骤1。
意思就是,可以通过设置max-age
来控制浏览器,在这个时间内,强行读取缓存,给网站提速。因此得名强缓存。
应用场景
一般我们项目的index.html
不设置缓存每次访问都必须从服务端拿, 但是js文件和css文件,会设置成强缓存并且时间都特别长。这样二次访问这些资源文件时,都会从浏览器缓存拿。
这么设计的底层逻辑是什么呢?
答:
项目中,我们的js/css这些资源文件经常变化,为了节省网络io,不能每次都更新所有的资源文件吧,这也太没有用户体验了。所以我们把文件拆分成小文件打包,并且加上hash,文件名为name.hash.js
。这样当资源更新后,hash就会更新,然后对于浏览器来说这就是一个全新的资源,得从服务端获取。这样保证了旧文件从缓存拿,新文件从服务端重新获取。
至于为什么index.html为什么不设置缓存, 因为index.html是入口啊,所以的资源文件都是从index.htm来的,你要是index.html都走缓存,资源一直都请求旧的资源了。太离谱了。
协商缓存
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。
缓存标识
控制协商缓存的字段分别有:Last-Modified / If-Modified-Since和Etag / If-None-Match。 对于这些概念,直接引用一下,大致明白就行。
- Last-Modified是服务器响应请求时,返回该资源文件在服务器最后被修改的时间
- If-Modified-Since则是客户端再次发起该请求时,携带上次请求返回的Last-Modified值,通过此字段值告诉服务器该资源上次请求返回的最后被修改时间。服务器收到该请求,发现请求头含有If-Modified-Since字段,则会根据If-Modified-Since的字段值与该资源在服务器的最后被修改时间做对比,若服务器的资源最后被修改时间大于If-Modified-Since的字段值,则重新返回资源,状态码为200;否则则返回304,代表资源无更新,可继续使用缓存文件
- Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成)
- If-None-Match是客户端再次发起该请求时,携带上次请求返回的唯一标识Etag值,通过此字段值告诉服务器该资源上次请求返回的唯一标识值。服务器收到该请求后,发现该请求头中含有If-None-Match,则会根据If-None-Match的字段值与该资源在服务器的Etag值做对比,一致则返回304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为200
优先级: Etag/If-None-Match > Last-Modified/If-Modified-Since
缓存过程
服务端如何根据缓存标识来判断是否使用缓存。 通过缓存标识, 来比对出文件是否更新过,未更新则返回304,更新返回200。
优点
协商缓存虽然也需要请求服务端,但是省下了文件传输的时间,这个时间才是大头。