先叠个甲
本文章是作者学习前端网络部分知识的一个记录,所有的知识点不保证100%准确。若有不准确的地方,请您及时指正,感谢!
本文章会向你介绍前端缓存(http缓存),以及缓存的使用场景。作者希望用简短的语言介绍该知识点,如果你不喜欢长篇大论的文章,那看这一篇就够了。
啥是缓存?
缓存是一种临时存储机制,能够将第一次获取的内容保存在本地(内存或硬盘中),以便在后续访问时直接从本地读取,而无需重新请求服务器。这样既可以提升请求速度、降低服务器的负载,又减少不必要的网络传输。
啥是HTTP缓存?
http缓存分为强缓存和协商缓存。
简单来说,强缓存就是第一次请求成功后,服务器响应了一个过期时间,在这个过期时间之内,下次请求该地址时,浏览器无需请求服务器,直接从本地读取内容并响应。而协商缓存就是第一次请求成功后,服务器返回内容后,每次请求还要向服务器询问是否可以使用缓存,如果得到允许,才能使用本地缓存的内容。
下面详细介绍一下这两种缓存策略
强缓存
通过Cache-Control实现强缓存
假设服务器想对https://www.image.com/abc进行强缓存,服务器会设置它的响应头为
'Cache-Control':'max-age=100'
当浏览器访问该url,并拿到响应结果后,看到这段响应头,浏览器就会把响应的内容缓存下来,往后100秒内,再访问此url地址,浏览器不会向服务器交互,而是直接从本地获取内容,并响应。
Cache-Control有多个属性,我挑几个重要的属性讲解。
max-age
资源缓存的时间,例如'Cache-Control':'max-age=1000',代表该资源从服务器响应后,浏览器缓存1000秒,这1000秒内,浏览器会使用本地缓存。超过1000秒,进行协商缓存。(协商缓存下面会介绍)
no-cache
强制进行协商缓存。例如'Cache-Control':'no-cache',代表该资源从服务器响应后,不进行强缓存而是协商缓存。
no-store
不进行任何缓存
这里要注意,
no-cache虽然译为无缓存或不缓存,但在Cache-Control中他的意思是协商缓存。no-store才是无缓存或不缓存的意思,这里千万不要搞混!
通过Expires实现强缓存
Expires是HTTP/1.0的字段,他已经被Cache-Control替代,这里简单讲一下。
假设服务器想对https://www.image.com/abc进行缓存,并使用Expries方案,服务器会设置它的响应头为
Expires: Wed, 21 Oct 2025 07:28:00 GMT
他的意思是:浏览器在 2025 年 10 月 21 日 07:28:00 之前可以直接使用缓存,而无需再次请求服务器。超过该时间后,浏览器会重新请求服务器以获取更新内容。
Expires的时间被Cache-Control替代的原因是,Expires返回的是一个具体的时间,而Cache-Control返回的是一个倒计时(单位是秒),这里有个问题,假设本地的时间不准或有变更,Expires缓存的时间可能会变长或变短,甚至永久缓存。
为了向下兼容,有时会看到服务器同时设置 Expires 和 Cache-Control,例如:
Cache-Control: max-age=600
Expires: Wed, 21 Oct 2025 07:28:00 GMT
这种情况下,Cache-Control 的 max-age 优先级更高。如果 max-age 和 Expires 的值不同,浏览器会优先使用 Cache-Control: max-age 的时间。
协商缓存
假设服务器想对https://www.image.com/abc进行协商缓存,服务器会设置它的响应头为
Cache-Control: no-cache
ETag: "abc123" // 唯一标识符
Last-Modified: Wed, 01 Jan 2024 00:00:00 GMT // 最后修改时间
ETag和Last-Modified是常用的两个响应头,它们用于标识资源的变化。
这里简单介绍一下ETag与Last-Modified
ETag是资源生成的hash值(文件指纹),如果文件内容为Hello, World!,可以计算其 MD5 哈希值(例如65a8e27d8879283831b664bd8b7f0ad4),并作为ETag。
Last-Modified是资源文件上一次的修改时间
当浏览器在响应成功后,在响应头读取到ETag与Last-Modified,并且Cache-Control: no-cache ,会将资源缓存,并在下次的请求头中携带字段:
If-None-Match: "abc123" // 使用上次获取的ETag
If-Modified-Since: Wed, 01 Jan 2024 00:00:00 GMT // 使用上次获取的Last-Modified
服务器验证时间与文件指纹正确后,就会返回304状态码,允许浏览器使用本地缓存。
读到这大家有没有看懂协商缓存与强缓存的区别,他们的区别就是强缓存第一次得到响应后,在特定的时间(max-age未过期)内,自动使用本地缓存。而协商缓存需要每一次都向服务器验证缓存的资源是否有效,得到服务器的验证后才会使用缓存。
注意:有时候服务器不一定同时返回
ETag与Last-Modified,因为ETag需要将文件内容进行hash编码,这个过程会给服务器造成压力。假设服务器没有返回ETag,浏览器在下次请求时,也就不会在响应头携带If-None-Match。
Last-Modified同理。
强缓存与协商缓存同时存在的情况
还记得Cache-Control的max-age属性吗?我最后写了一句话:“超过1000秒,进行协商缓存”。
这时可能会有疑惑,max-age不是强缓存吗?
这里我想说一下,max-age也可以做协商缓存。下面我来举个例子。
假设你第一次请求某个资源,服务器可能会设置响应头为:
Cache-Control: max-age=1000
ETag: "abc123"
Last-Modified: Wed, 01 Jan 2024 00:00:00 GMT
这代表在1000秒之内,服务器默认使用强缓存。在1000秒内请求该地址,浏览器会直接使用本地资源。超过1000秒之后,浏览器会带上 If-None-Match 和 If-Modified-Since 进行协商缓存验证。服务器如果验证通过并返回 304 状态码,则继续使用本地缓存;否则,返回新的内容。
用人话说就是,浏览器在1000秒之内使用强缓存,超过1000秒之后,浏览器不知道该资源是否过期,它还不想直接放弃这个资源的本地缓存,所以会带上 If-None-Match 和 If-Modified-Since去进行协商缓存验证。
写在最后
感谢您能看完,如有任何错误,请在评论区或私信联系我,我会立刻改正!