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

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

相关推荐
VT.馒头7 分钟前
【力扣】2625. 扁平化嵌套数组
前端·javascript·算法·leetcode·职场和发展·typescript
数研小生35 分钟前
Full Analysis of Taobao Item Detail API taobao.item.get
java·服务器·前端
Shirley~~1 小时前
Vue-skills的中文文档
前端·人工智能
毎天要喝八杯水1 小时前
搭建vue前端后端环境
前端·javascript·vue.js
计算机程序设计小李同学1 小时前
幼儿园信息管理系统的设计与实现
前端·bootstrap·html·毕业设计
雨季6662 小时前
Flutter 三端应用实战:OpenHarmony “专注时光盒”——在碎片洪流中守护心流的数字容器
开发语言·前端·安全·flutter·交互
tao3556672 小时前
【用AI学前端】HTML-02-HTML 常用标签(基础)
前端·html
2601_949532842 小时前
Psello HTML Template: A Developer‘s Deep-Dive Review and Guide - Download Free
前端·windows·html·seo·wordpress·gpl
CappuccinoRose2 小时前
CSS前端布局总指南
前端·css·学习·布局·flex布局·grid布局·float布局
穿过锁扣的风2 小时前
如何操作HTML网页
前端·javascript·html