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或更高版本协议,就可以支持协商缓存机制。

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

相关推荐
用户新4 小时前
V8引擎 精品漫游指南--Ignition篇(下 一) 动态执行前的事情
前端·javascript
@PHARAOH5 小时前
WHAT - GitLens vs Fork
前端
yqcoder5 小时前
前端性能优化:如何减少重绘与重排?
前端·性能优化
洋子6 小时前
Yank Note 系列 13 - 让 AI Agent 进入笔记工作流
前端·人工智能
wenzhangli78 小时前
Ooder A2UI 核心架构深度解析:WEB 拦截层的设计与实现
前端·架构
前端百草阁9 小时前
【前端性能优化全链路指南】从开发编写到构建运行的多维度实践
前端·性能优化
女生也可以敲代码9 小时前
AI时代下的50道前端开发面试题:从基础到大模型应用
前端·面试
ZhengEnCi9 小时前
M5-markconv自定义CSS样式指南 📝
前端·css·python
IT_陈寒9 小时前
SpringBoot自动配置的坑差点让我加班到天亮
前端·人工智能·后端
xingpanvip9 小时前
星盘接口开发文档:星相日历接口指南
android·开发语言·前端·css·php·lua