浏览器缓存

#积累/浏览器原理

缓存查找流程

  1. 发起资源请求,首先浏览器会在浏览器缓存中查找是否有请求的文件,如果有缓存的文件,且缓存未过期,则使用缓存;
  2. 如果没有缓存该文件,则向服务器发起请求,服务器直接响应内容;
  3. 如果有缓存的文件,但缓存时间过期,则携带缓存文件标识符正式发起请求。服务器根据标示符比对文件是否有更新,如果未修改,则响应304,使用过期缓存;如果已经更新,则直接响应内容。

什么是强制缓存和协商缓存?

强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程。
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程

服务器是通过什么方式让浏览器缓存数据的?

::Cache-Control / Expires::
当服务器返回 HTTP 响应头给浏览器时,浏览器是通过响应头中的 Cache-Control字段(HTTP/1.1)或Expires字段(HTTP/1.0)来设置是否缓存该资源。
比如上图设置的缓存过期时间是 2000 秒:

1
Cache-Control:Max-age=2000

也根据Cache-Control或Expires来判断资源是否过期,如果未过期则使用缓存文件,如果过期则正式发起请求

  • Cache-Control和Expires同时存在时,只有Cache-Control生效。

服务器如何比对资源是否修改?

::Last-Modified / If-Modified-Since::
Last-Modified是服务器响应请求时,返回该资源文件在服务器最后被修改的时间;
If-Modified-Since则是客户端再次发起请求时,携带上次请求返回的Last-Modified值,通过此字段值告诉服务器该资源上次请求返回的最后被修改时间;
服务器根据If-Modified-Since信息和该资源在服务器的最后被修改时间,判断响应304,还是响应新内容。

::Etag / If-None-Match::
Etag是服务器响应时,返回当前资源文件的一个唯一标识(由服务器生成);
If-None-Match是浏览器发现缓存过期再次请求时,携带的上次请求返回的唯一标识Etag值;
服务器根据If-None-Match的字段值与该资源在服务器的Etag值做对比,如果文件未更新则响应304,如果已更新则响应新内容。

  • Etag / If-None-Match优先级高于Last-Modified / If-Modified-Since,同时存在则只有Etag / If-None-Match生效。

Ctrl+F5和F5有什么区别?

  • 一个是强制刷新,也就是资源都走网络。
  • 一个是正常处理流程,缓存机制还起作用。还包括这些浏览器操作:在URI输入栏中输入地址并回车、右键菜单重新加载、点击工具栏中的刷新按钮

其他

Cache-control参数

Cache-Control定义资源的缓存策略

  • no-cache, no-store
    no-cache: 浏览器不做缓存,每次请求资源都会发起请求,etag没有变化、服务器返回304,则不再重新下载资源;
    no-store:浏览器和cdn均不做缓存,并且每次请求资源都会发起请求,并重新下载资源
  • public, private
    当存在私密信息、时效性高的数据,则需要设置。
    public: 可以缓存,即使保护用户隐私信息;
    private:不允许cdn缓存,防止用户信息泄露。
  • max-age
    指定从请求开始,允许被重用的最长时间(单位秒)。
    当设置了max-age,资源在指定的时间内不会发送请求到服务器
  • 例子
    max-age=86400:
    浏览器以及任何中间缓存均可将响应(如果是“public”响应)缓存长达 1 天(60 秒 x 60 分钟 x 24 小时)。
    private, max-age=600:
    客户端的浏览器只能将响应缓存最长 10 分钟(60 秒 x 10 分钟)。
    no-store:
    不允许缓存响应,每次请求都必须完整获取。
  • nginx配置cache-control
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    location ~ .*\.(css|js|swf|php|htm|html )$ {
    add_header Cache-Control no-store;
    add_header Pragma no-cache;
    }
    location ~* \.(gif|jpg|jpeg|bmp|png|ico|txt|js|css)$ {
    expires 30d;
    }

    location ~* \.html?$ {
    expires 10m;
    }
    最终响应中会添加以下属性:
    * ### Cache-Control:max-age=600
    * ### Expires:Sat, 23 Mar 2019 14:37:35 GMT
    * ### ETag:"5c962c53-15b"
    * ### Last-Modified:Sat, 23 Mar 2019 12:53:39 GMT

配置Etag

  • 服务器会响应ETag,去唯一标示资源。当资源有变化,ETag也会改变。
  • 客户端收到ETag之后,浏览器会在请求头中加入If-None-Match,传递ETag值。
  • 服务器比对ETag,发现没有变化,则可以通过响应304 Not Modified,来避免重新下载资源。
  • nginx开启ETag
    1
    2
    3
    4
    5
    http{
    ...
    etag on;
    ...
    }

缓存策略

  • 入口文件设置no-cache,不做缓存;
  • 所有图片、静态文件,都做长时间的缓存
  • 所有图片、静态文件,文件名设置hash值,并每天更新同时更改入口文件的引入文件名