前端静态资源缓存策略

133 阅读3分钟

缓存策略作为前端性能优化的重要环节,直接影响用户体验。若使用了缓存策略,用户二次访问时加快页面打开速度,提高用户体验,另外还能降低服务器压力。

一、浏览器缓存机制

1.1 强缓存

不使用缓存image.png

使用缓存image.png

我们可以看到消耗的时间from memory cache的时候为0,from disk cache的时候也减少了60%以上。

1.1.1 memory cache和disk cache的区别

缓存类型读取位置读取速度生命周期
memory cache内存读取速度快,优先级高生命周期短,页面关闭就释放内存,只能存小文件
disk cache硬盘读取速度相对较慢生命周期长,不手动删除会一直存在,可存储大文件

1.1.2 强缓存字段

浏览器首次请求资源时,当服务器收到请求,可根据请求资源类型,在HTTP响应头(Response Headers) 中添加强缓存控制字段Expires和Cache-Control,浏览器根据标识将资源进行缓存。

优先级响应头
Expires低(HTTP/1.0)Expires: Fir, 11 Aug 2023 02:29:06 GMT 过期时间,可能因为时区不同或客户端和服务端时间有误差等原因,导致强缓存失效
Cache-Control高(HTTP/1.1)Cache-Control: max-age=2592000 一个相对值,根据当前时间计算出过期时间

Cache-Control取值:

  • public: 代理服务器或中间服务器,客户端都可以缓存该内容
  • private(默认值):只有客户端能缓存
  • no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定
  • no-store:不使用缓存,既不使用强缓存也不使用协商缓存
  • max-age=xxx:缓存内容在xxx秒后失效 image.png

1.2 协商缓存

我们有时候还能看到有状态码为304的请求,这就是协商缓存生效的结果。 image.png

1.2.1 协商缓存字段

  1. Last-Modified/If-Modified-Since: Last-Modified:服务器响应头,该资源在服务器最后被修改的时间。 If-Modified-Since:客户端再次发起该请求时,携带的上次请求回来的Last-Modified值,服务器收到之后与该资源最后一次修改的时间做对比,若大于该值,则表示该资源被修改了,重新返回资源,状态码为200,否则表示未被修改,状态码为304,告诉客户端继续使用缓存内容。
  2. Etag/If-None-Match: Etag:当前资源的唯一标识,由服务端生成。 If-None-Match:客户端再次发起请求时,携带上次请求回来的Etag,服务器端收到后,将其与资源的Etag做对比,若不同,则返回最新资源,状态码为200,否则表示未被修改,状态码为304,告诉客户端继续使用缓存内容。

注:Etag优先级高于Last-Modified,因为修改时间,可能会因为时区或客户端与服务器时间不一致,导致失效。

image.png

1.3 请求资源的过程

缓存.png

二、前端静态资源缓存策略

前端哪些资源是需要强缓存,哪些需要协商缓存?

2.1 前端静态资源

前端静态资源一般包括:js,css,图片

我们在使用打包工具打包时,通常会对js/css文件输出带hash的路径,或对经常变化的文件生成为chunk。

以webpack为例: image.png

打包后的结果为: image.png

2.2 缓存策略

我们整体的策略是对带hash路径和图片类的资源进行强缓存,其他的进行协商缓存。

以 Nginx 为例,做以下配置:

    location / {
        if ($request_filename ~* ^.*[.](html|htm)$) {
            # html文件不缓存
            expires 0;
            add_header Cache-Control "no-store";
        }
        
        if ($request_filename ~* .*.(js|css|json)$) {
            # 不带hash的js,css,json协商缓存
            add_header Cache-Control "no-cache";
        }
        
        if ($request_filename ~* .*.(chunk).(css|js)$) {
            # 带hash的js,css强缓存一个月
            add_header Cache-Control "max-age=2592000";
        }
        
        if ($request_uri ~* .*[.](png|jpg|svg|ico)$) {
            # 图片强缓存一个月
            add_header Cache-Control "max-age=2592000";
        }
    }