Skip to content

浏览器缓存

强缓存

通过设置 过期时间 来决定是否采用缓存返回 200 状态码

  • 未过期:直接从浏览器缓存中读取,无论资源是否过期
  • 过期了:从服务器请求

Expires - HTTP/1.0

值为一个时间戳,服务器返回该请求结果缓存的到期时间,意思是,再次发送请求时,如果未超过过期时间,直接使用该缓存,如果过期了则重新请求。

缺点: 用本地时间来判断是否过期,但是本地时间是可以自己修改的。

HTTP/1.0 可以设置 pragma: no-cache 来跳过缓存

Cache-Control - HTTP/1.1

  • private:仅浏览器可以缓存(默认值);
  • public:浏览器和代理服务器都可以缓存;
  • max-age=xxx:过期时间单位秒(解决了 Expires 自己修改本地时间的问题)
  • no-cache:不进行强缓存;
  • no-store:不强缓存,也不协商缓存
  • no-transform:不对传输的内容做任何转码(常见的地方为 proxy 或 browser 为了减少传输内容及流量,会对传输的图片等进行格式转换,此配置可以避免转换)

img

协商缓存

强缓存失效后,浏览器携带缓存标识向服务器发送请求,由服务器根据缓存标识来决定是否使用缓存的过程。

  • 协商缓存生效:304
  • 协商缓存不生效:200

Last-Modified / If-Modified-Since

  • Last-Modified:服务器响应请求(Response Header),表示该资源文件在服务器最后被修改的时间
  • If-Modified-Since:客户端请求头(Request Header), 携带上次请求拿到的 Last-Modified 若服务器的资源最后被修改时间大于 If-Modified-Since 的字段值,则重新返回资源,状态码为 200;否则则返回 304,代表资源无更新,可继续使用缓存文件

ETag / If-None-Match

为什么要有 etag?

ETag 的精度更高,Last-Modified 的时间单位是秒,如果一个文件 1s 内修改了多次,Last-Modified 无法感知到每次的变化

  • ETag:服务器响应请求(Response Header),表示当前文件的唯一标识。
  • If-None-Match:客户端请求头(Request Header), 携带上次请求拿到的 ETag ,若与服务器的资源一致,代表资源无更新,可继续使用缓存文件 返回 304,否则返回 200

缓存位置

它们的优先级是:(由上到下寻找,找到即返回;找不到则继续)

1. Service Worker

Service Worker(服务工作线程)是一种在Web浏览器背后运行的脚本,它独立于网页,并提供一种在后台执行任务的方式。

Service Worker 的引入使得开发者能够实现一些先前难以实现的功能,例如离线缓存、推送通知和后台同步。

Service Worker 的特性和用途:

  1. 独立于页面: Service Worker 运行在单独的线程中,与网页分离。这意味着即使用户关闭了网页,Service Worker 仍然可以在后台运行。
  2. 网络代理: Service Worker 充当浏览器和网络之间的代理,使其能够拦截和处理网络请求。这使得开发者可以自定义缓存策略,实现离线浏览或提高应用程序性能。
  3. 离线缓存: 使用 Service Worker,开发者可以将网页资源缓存到本地,以便在离线时仍然能够提供基本的用户体验。这对于移动设备或不稳定网络连接的环境尤其有用。
  4. 推送通知: Service Worker 允许向用户发送推送通知,即使用户当前没有打开相应的网页。这可以用于实现实时更新、提醒和其他通知功能。
  5. 后台同步: Service Worker 可以在后台执行任务,例如与服务器同步数据。这使得应用程序能够在用户没有打开网页的情况下进行数据更新和同步。
  6. 安全性: 由于 Service Worker 运行在一个与网页分离的上下文中,它受到严格的安全性控制,以防止恶意行为。

2. Memory Cache

内存缓存的优势在于读写速度非常快,因为它直接存储在计算机的内存中。

然而,由于内存有限,内存缓存的内容通常是短暂的,浏览器可以根据需要清除内存中的缓存。

常见的内存缓存包括:

  • 浏览器内存缓存: 浏览器会将最近请求的资源(例如图片、样式表、脚本等)存储在内存中,以便在同一页面中的其他请求可以更快地访问这些资源。
  • JavaScript引擎内存: JavaScript 运行时也使用内存缓存来存储已经执行过的脚本和相关数据,以提高后续对相同代码的执行速度。

3. Disk Cache

磁盘缓存是一种将数据存储在硬盘或其他持久性存储介质中的缓存方式。

不同于内存缓存,磁盘缓存的数据可以在多次会话之间保留,即使用户关闭浏览器,数据仍然可以被保留。

常见的磁盘缓存包括:

  • 浏览器磁盘缓存: 浏览器将已下载的资源(例如HTML、CSS、JavaScript文件)存储在用户的硬盘上,以便在用户下次访问相同页面时可以更快地加载这些资源,从而提高网页加载速度。
  • 服务器端磁盘缓存: 服务器可以将一些静态或不经常变化的内容(如图片、视频、样式表等)缓存到磁盘上,以减轻服务器的负载并提高响应速度。

浏览器刷新

  • **打开网页,地址栏输入地址:**查找 disk cache 中是否有匹配。如有则使用;如没有则发送网络请求
  • **普通刷新 (F5):**因为 TAB 并没有关闭,因此 memory cache 是可用的,会被优先使用(如果匹配的话)。其次才是 disk cache。
  • **强制刷新 (Ctrl + F5):**浏览器不使用缓存,因此发送的请求头部均带有 Cache-control: no-cache(为了兼容,还带了 Pragma: no-cache),服务器直接返回 200 和最新内容。

缓存方案

目前的项目大多使用这种缓存方案的:

  • HTML: 协商缓存;
  • **css、js、图片:**强缓存,文件名带上 hash

总结

  • Expires 和 Cache-Control 决定了浏览器是否要发送请求到服务器,ETag 和 Last-Modified 决定了服务器是要返回 304+空内容还是新的资源文件
  • Expires 和 Cache-Control 同时存在时,Cache-Control 会覆盖 Expires
  • ETag 和 Last-Modified 同时存在时,两者都要满足才会返回 304

参考