web缓存问题的解决方案

背景

单页面应用

现代前端框架大多数走的是单页面应用路线,vue项目即是。对于这类应用,浏览器加载的内容主要为:

  1. 入口html文件:index.html
  2. 资源文件:chunk-vendors.*

浏览器缓存机制

浏览器缓存机制会使浏览器缓存许多类型的HTTP请求,包括.html.js.css

浏览器缓存机制的目的在于减少网络请求,提高网页加载速度,优化用户体验。也许有些时候它很讨厌:

有新更新的时候

但有的时候它很可爱:

当用户加载页面需要长达5s甚至更长的时间时

相比起可爱之处,它的讨厌之处是可以通过一些方法化解的。这就是接下来的内容。

缓存问题的解决之道

综上所述,要解决缓存带来的困扰,我们需要:

  1. 使得客户端及时更新index.html,只有这样才能够有机会更新.js.css文件。以下是一个模拟的index.html资源,用于理解为什么"只有这样"

    xml 复制代码
    <html>
        <head>
        /*省略其他项*/
        <link href="xx/xx/chunk-vendors.css"></link>
      </head>
        <body>
        <script type="text/javascript" src="xx/xx/chunk-vendors.js"></script>
        </body>
    </html>

    单页面应用中的资源文件.js.css是要通过index.html加载的。但是在完成版本更新之后,我们大多数时候已经移除了上一版本的js包,可是客户端仍能顺利完成加载,这是因为,连资源文件也一并缓存了。

  2. 更新资源文件,这里应该被分为两个部分:客户端请求新的资源文件(依赖index.html的更新),服务端提供新的资源文件。这里可以通过添加hash命名的方式使得新的index.html中使用新的资源包名,打包出来的资源文件也是对应的新包名

    xml 复制代码
    <html>
        <head>
        /*省略其他项*/
        <link href="xx/xx/chunk-vendors.78ushgag7y.css"></link>
      </head>
        <body>
        <script type="text/javascript" src="xx/xx/chunk-vendors.fgwjkrhakg23.js"></script>
        </body>
    </html>

    中间的乱码是模拟的hash值

1.入口文件index.html

这里采用协商缓存机制解决index.html的缓存

step-1.服务端添加响应头

arduino 复制代码
Cache-Control: 'private no-cache'

其中:

  • private: 仅允许响应被发送请求的客户端缓存(排除可能的中间代理的缓存)
  • no-cache: 客户端缓存内容,但是否使用缓存需要经过协商缓存决定

这个需要在nginx等服务器上匹配index.html的请求路径,添加响应头实现

这里需要说明,仅仅在页面上添加<meta http-equiv="Cache-Control" content="no-cache" />是不够的,因为浏览器在处理缓存时,依赖于 HTTP 响应头中的 Cache-Control,所以这部分应该由服务端进行设置

step-2.协商缓存

1-首次请求资源时,服务器会在响应头中包含ETagLast-Modified

Nginx默认会为静态文件生成ETag

其他服务器应该也有类似实现

2-客户端再次请求时,在请求头中加入If-None-MatchorIf-Modified-since

If-None-Match: 上次响应头中的Etag

If-Modified-since: 上次响应头中的Last-Modified

3-服务器验证

有两对头信息可以用于协商缓存。

If-None-Match&ETag

If-Modified-since&Last-Modified

服务器比较请求头If-None-Match与当前的ETagIf-Modified-since与当前的Last-Modified是否匹配。

  • 匹配:触发304 Not Modified响应告诉浏览器使用缓存的版本
  • 不匹配:返回新的响应(新的静态页面、ETagLast-Modified)

2.资源文件

应用打包时配置hash打包即可,这样打包之后的资源文件就会带上hash值避免重复。

由于不同的打包工具、不同的插件应用有不同的写法,这一步可以自由尝试。

总结

通过以上方式,可以有效解决浏览器缓存问题,包括微信小程序的webview缓存。目前已测试较新的IOS机器和Android机器。

同时注意到:

协商缓存机制主要依赖于HTTP协议而不是浏览器特性,以上提到的HTTP头在HTTP/1.1规范中定义,这就意味着只要浏览器支持HTTP/1.1或更高版本协议,就可以支持协商缓存机制。

具体的行为也会受到浏览器设置、用户行为、网络条件的影响,因此更重要的是参考实际情况。比如在浏览器中用户手动进行了缓存设置的情况。

相关推荐
coding随想2 小时前
还没用过就要被弃用了?深度解析浏览器中的App Cache缓存管理事件
前端
Flyfreelylss2 小时前
前端实现解析【导入】数据后调用批量处理接口
前端·reactjs
小彭努力中2 小时前
164.在 Vue3 中使用 OpenLayers 加载 Esri 地图(多种形式)
开发语言·前端·javascript·vue.js·arcgis
布里渊区2 小时前
前端页面性能优化
前端·性能优化
浩星2 小时前
react+taro中使用vant 工具:taroify
前端·react.js·taro
浩星2 小时前
react+taro的使用整理
前端·react.js·taro
IT_陈寒3 小时前
7个Vue 3.4新特性实战心得:从Composition到性能优化全解析
前端·人工智能·后端
@HNUSTer3 小时前
基于 HTML、CSS 和 JavaScript 的智能图像锐化系统
开发语言·前端·javascript·css·html
B.-3 小时前
前端静态资源缓存与部署实践总结
前端·javascript·缓存·html
Mintopia3 小时前
注意力机制如何让 WebAI 的上下文理解“开了天眼”?
前端·javascript·aigc