老规矩,想要了解学会一项技术,先从定义下手!
浏览器的缓存的定义
浏览器的缓存是指浏览器在处理网络资源时,将这些资源存储在本地磁盘或内存中,并在后续的请求中重复使用这些缓存的资源。它旨在提高网页加载速度、减少网络流量和服务器负载。
为什么要进行缓存?
- 提升网页加载速度:浏览器缓存能够存储网页的静态资源,下次访问时直接从缓存中加载,避免了不必要的服务器请求,从而加快了网页加载速度,提升用户体验。
- 减少网络流量:通过从缓存中加载资源,浏览器可以避免重复的网络请求,减少数据传输量,节省了用户的网络流量费用。
- 降低服务器负载:浏览器缓存减少了对服务器的请求次数,降低了服务器的负载压力。特别对于繁忙的网站而言,可以更好地处理并发请求,提高服务器的性能和响应能力。
- 改善用户体验:快速的网页加载速度和较低的网络延迟显著改善了用户体验。用户能够更快地获取所需信息,减少等待时间,提高用户满意度。
- 离线访问能力:对于具有离线访问能力的应用程序(如PWA),浏览器缓存可以存储应用程序的核心文件和数据,使得用户在没有网络连接的情况下仍然能够访问应用程序并查看之前加载过的内容。
尽管浏览器缓存具有许多优势,但也存在一些潜在的缺点:
- 缓存更新延迟:由于浏览器缓存的存在,用户无法立即获取到最新的内容,可能导致用户看到过时的信息,影响用户体验。
- 缓存一致性问题:如果多个地方缓存了同一资源,当一个地方的资源更新时,其他地方的缓存可能仍然是旧的版本,导致显示不一致的内容或功能异常。
- 缓存过期管理:缓存需要定期更新以确保用户获取到最新的内容,但过期管理可能复杂,设置不当或策略不当可能导致用户无法及时获取更新的内容。
- 缓存容量限制:浏览器对缓存的容量有限制,如果缓存的资源过多或占用过大空间,可能影响其他重要资源的缓存或加载性能。
- 隐私和安全问题:浏览器缓存可能存储敏感信息,如果用户共享设备或使用不受信任的设备,可能面临缓存数据被访问或滥用的风险。同时,缓存也可能成为恶意攻击者的目标,用于攻击或窃取数据。
但是总体来说浏览器的缓存还是优势大于劣势,是我们优化网站性能最优选择
缓存的类别
浏览器的缓存机制通常分为两个方面:强缓存和协商缓存。或者是缓存中的数据可能与服务器的数据不一致。
两者的主要区别是使用本地缓存的时候,是否需要向服务器验证本地缓存是否依旧有效。顾名思义,协商缓存,就是需要和服务器进行协商,最终确定是否使用本地缓存。
什么是强缓存?
强缓存是指浏览器在请求资源时,直接从本地缓存中获取资源,并且不会发送请求到服务器。
强缓存是如何实现的呢?
强缓存是通过设置HTTP响应头来实现的。主要有两种方式来设置强缓存:
-
Expires
:服务器在响应头中设置一个过期时间,表示资源的有效期。浏览器在下一次请求该资源时,会先比较当前时间与资源的过期时间,如果未过期,则直接使用缓存副本。但是这种方式存在一个问题,比如服务器与客户端时间不一致可能导致缓存失效。为了解决这个问题就有了Cache-Control。 -
Cache-Control
:通过设置Cache-Control响应头来控制缓存行为。常见的取值有:max-age=<seconds>
:指定资源的最大缓存时间,以秒为单位。例如,Cache-Control: max-age=3600
表示资源将在 3600 秒(1小时)后过期。浏览器在该时间内直接使用缓存,而不发送请求到服务器。no-cache
:要求客户端每次请求都要发送验证请求到服务器,以确认缓存的副本是否仍然有效。即使客户端有缓存副本,也必须进行重新验证。no-store
:指示客户端不应将响应存储在任何缓存中,包括临时缓存。每次请求都需要重新从服务器获取资源。public
:表示响应可以被任何缓存(包括公共缓存和私有缓存)缓存。private
:指示响应只能被私有缓存缓存,不允许被共享缓存(如 CDN)缓存。must-revalidate
:要求客户端在缓存过期之前必须重新验证资源的有效性,如果资源无效,则需要从服务器重新获取。proxy-revalidate
:类似于must-revalidate
,但仅适用于共享缓存(如 CDN)。
强缓存的过程
浏览器第一次请求,没有强缓存
- 用户发起请求:用户在浏览器中输入网址或点击链接,触发请求发送给服务器。
- 检查强缓存:浏览器首先检查缓存中是否存在所请求资源的副本,并且该副本是否仍然有效(未过期)。检查过程是根据请求的URL和响应头中的缓存相关字段进行匹配。
- 缓存未命中:如果缓存中不存在有效的副本,或者副本已过期(根据响应头中的过期时间或其他缓存控制字段),浏览器需要向服务器发送请求获取最新的资源。
- 服务器响应:服务器接收到请求后,会根据请求的URL和其他相关信息来生成响应。响应中包含了所请求资源的内容以及与缓存相关的响应头字段
- 更新缓存:浏览器从服务器获取到最新的资源后,会将资源存储在缓存中,以备将来使用。缓存中的副本会根据响应头中的缓存相关字段(如Cache-Control、Expires)进行更新和管理。
浏览器有强缓存,且未过期
- 用户发起请求:用户在浏览器中输入网址或点击链接,触发请求发送给服务器。
- 检查强缓存:浏览器首先检查缓存中是否存在所请求资源的副本,并且该副本是否仍然有效(未过期)。检查过程是根据请求的URL和响应头中的缓存相关字段进行匹配。
- 缓存命中:如果缓存中存在有效的副本,浏览器直接从缓存中获取资源,无需向服务器发送请求。这个过程称为缓存命中,可以大大加快网页加载速度。
- 返回缓存副本:浏览器从缓存中获取到资源后,将其返回给用户,并显示网页内容或执行相应的操作。
什么是协商缓存?
协商缓存是指浏览器在请求资源时,浏览器和服务器之间协商确定是否使用缓存副本的形式。
- 如果资源的强缓存失效(即过期),浏览器将向服务器发送请求,并在请求中携带上次缓存的相关信息。
- 服务器收到请求后,会根据携带的信息来判断资源是否有更新。
- 如果资源没有更新,则服务器返回一个空的响应,并在响应头中设置状态码为304(Not Modified),告诉浏览器可以使用本地缓存。
- 如果资源有更新,服务器将返回新的资源,并在响应头中设置相关的缓存信息。
协商缓存如何实现的:
协商缓存是通过设置HTTP响应头来实现的。主要有两种方式来设置强缓存:
Last-Modified 和 If-Modified-Since
:服务器在响应头中使用
Last-Modified 字段来指示资源的最后修改时间。当客户端发送请求时,在请求头中使用 。If-Modified-Since 字段将上次获取资源时服务器返回的 Last-Modified 时间戳发送回服务器。服务器接收到请求后,会比较资源的修改时间与 If-Modified-Since 字段的值相比较。如果资源未被修改,则返回状态码 304 Not Modified,客户端可以使用缓存副本。否则,返回最新的资源和状态码 200 OK。ETag 和 If-None-Match
:服务器在响应头中使用 ETag 字段来指示资源的标识符,通常是一个唯一的字符串。当客户端发送请求时,在请求头中使用 If-None-Match 字段将上次获取资源时服务器返回的 ETag 值发送回服务器。服务器接收到请求后,会比较资源的标识符与 If-None-Match 字段的值。如果标识符相同,则返回状态码 304 Not Modified,客户端可以使用缓存副本。否则,返回最新的资源和状态码 200 OK。
Last-Modified
:指示资源的最后修改时间。If-Modified-Since
:在后续请求中,浏览器通过该字段将上次的Last-Modified
值发送给服务器。ETag
(实体标签):是一个资源的唯一标识符,可以是资源的哈希值、版本号等。If-None-Match
:在后续请求中,浏览器通过该字段将上次的ETag
值发送给服务器。
协商缓存的实现过程
Last-Modified 和 If-Modified-Since
的协商缓存的过程如下:
- 客户端请求一个资源,服务器返回响应,其中包含 Last-Modified 字段,表示资源的最后修改时间。
- 客户端再次请求同一资源,但在请求头中添加 If-Modified-Since 字段,值为之前服务器返回的 Last-Modified 时间。
- 服务器接收到带有 If-Modified-Since 字段的请求后,会将资源的最后修改时间与该字段的值进行比较。
- 如果资源的最后修改时间与 If-Modified-Since 字段的值相同,表示资源未被修改,服务器会返回一个空的 304 Not Modified 响应,表示资源未改变。
- 如果资源的最后修改时间较新,表示资源已被修改,服务器会返回新的资源内容,并在响应头中更新 Last-Modified 字段,供下一次请求使用。
ETag 和 If-None-Match
的协商缓存的过程如下:
- 客户端请求一个资源,服务器返回响应,其中包含 ETag 字段,表示资源的版本标识符。
- 客户端再次请求同一资源,但在请求头中添加 If-None-Match 字段,值为之前服务器返回的 ETag 值。
- 服务器接收到带有 If-None-Match 字段的请求后,会将该值与资源的当前 ETag 进行比较。
- 如果两者匹配,表示资源未被修改,服务器会返回一个空的 304 Not Modified 响应,表示资源未改变。
- 如果两者不匹配,表示资源已被修改,服务器会返回新的资源内容,并在响应头中更新 ETag 字段,供下一次请求使用。
浏览器强缓存过期,且服务器数据更新了
- 用户发起请求:用户在浏览器中输入网址或点击链接,触发请求发送给服务器。
- 检查强缓存:浏览器首先检查缓存中是否存在所请求资源的副本,并且该副本是否仍然有效(未过期)。检查过程是根据请求的URL和响应头中的缓存相关字段进行匹配。
- 缓存未命中:如果缓存中不存在有效的副本,或者副本已过期(根据响应头中的过期时间或其他缓存控制字段),浏览器需要向服务器发送请求获取最新的资源。
- 服务器响应:服务器收到请求后,会对请求资源进行验证,判断是否有更新。
-. 如果资源已修改(验证失败):服务器会返回状态码200 OK,并返回最新的资源内容。 - 更新缓存:浏览器从服务器获取到最新的资源后,会将资源存储在缓存中,以备将来使用。缓存中的副本会根据响应头中的缓存相关字段(如Cache-Control、Expires)进行更新和管理。
总结
在浏览器缓存机制中,强制缓存优先于协商缓存进行处理。当强制缓存生效时,浏览器会直接使用缓存的资源,而不向服务器发送请求。强制缓存可以通过Expires和Cache-Control头字段来设置。
如果强制缓存不生效,浏览器将进行协商缓存。协商缓存通过使用Last-Modified / If-Modified-Since和Etag / If-None-Match头字段来与服务器进行通信,判断资源是否仍然有效。服务器会根据这些字段的值来决定是否使用缓存。
如果协商缓存失效,表示请求的缓存已过期或无效,浏览器将重新向服务器发送请求获取最新的资源,并将结果存入缓存中供下次使用。
如果协商缓存生效,服务器将返回304状态码,表示资源未发生变化,浏览器将继续使用缓存的资源,而无需重新下载。