浏览器缓存
浏览器缓存是浏览器在本地磁盘对用户最近请求过的文档进行存储,当访问者再次访问同一页面时,浏览器就可以直接从本地磁盘加载文档。 浏览器缓存主要分为 强缓存
(也称本地缓存)和 协商缓存
(也称弱缓存)。
强缓存
:当请求资源的时,如果是之前请求过的并使用强缓存,那么在过期时间内将不会发送本次请求向服务器获取资源,而是直接从浏览器缓存中获取(不管资源是否改动)。过期了将重新从服务器获取,并再次强缓存。协商缓存
:当请求资源时,如果是之前请求过的并使用协商缓存,还是发送请求到服务器,服务器通过逻辑判断确认资源没有修改返回304
状态码,那么本次的资源则是从缓存中获取;如果经过判断确认资源被修改过,则重新发送资源到客户端,并且客户端更新缓存。
缓存流程
强缓存
第一次访问页面,浏览器会根据服务器返回的 response Header
来判断是否对资源进行缓存,如果响应头中有 Cache-control
或 Expires
字段,代表该资源是强缓存,Expires
是 http1.0
的规范,Cache-Control
是在 http1.1
中出现的。
Cache-Control
有一些常设置的值:
属性 | 描述 |
---|---|
public | 资源客户端和服务器都可以缓存 |
privite | 资源只有客户端可以缓存 |
no-cache | 客户端缓存资源,但是是否缓存需要经过协商缓存来验证 |
no-store | 不使用缓存 |
max-age | 缓存保质期,是相对时间 |
Expires
是 HTTP1.0
控制网页缓存的字段,值为一个时间戳,服务器返回该资源缓存的到期时间
但 Expires
有个缺点,就是它判断是否过期是用本地时间来判断的,本地时间是可以自己修改的
到了 HTTP/1.1
,Expire
已经被 Cache-Control
替代,Cache-Control
使用了 max-age
相对时间,解决了 Expires
的缺陷
注意:当 Cache-Control
与 expires
两者都存在时,Cache-Control
优先级更高
memory cache 与 disk cache 的区别?
两者都属于 强缓存
,主要区别在于存储位置和读取速度上:
memory cache
表示缓存来自内存,disk cache
表示缓存来自硬盘memory cache
要比disk cache
快的多!从磁盘访问可能需要 5-20 毫秒,而内存访问只需要 100 纳秒甚至更快memory cache
特点:当前tab
页关闭后,数据将不存在(资源被释放掉了),再次打开相同的页面时,原来的memory cache
会变成disk cache
disk cache
特点:关闭tab
页甚至关闭浏览器后,数据依然存在,下次打开仍然会是from disk cache
提示
一般情况下,浏览器会将 js
和图片等文件解析执行后直接存入内存中,这样当刷新页面时,只需直接从内存中读取(from memory cache
),而 css
文件则会存入硬盘文件中,所以每次渲染页面都需要从硬盘读取缓存(from disk cache
)
协商缓存
浏览器携带缓存标识向服务器发送请求,服务器根据缓存标识来决定该资源是否过期,一般用于 html
资源,验证版本是否更新
触发条件:
Cache-Control
的值为no-cache
(协商缓存)- 或者
Cache-Control
:max-age=0
协商缓存的标识
Last-Modified
:文件在服务器最后被修改的时间,从服务器Respnse Headers
上获取:Last-Modified
的验证流程:- 第一次访问页面时,服务器的响应头会返回
Last-Modified
字段 - 客户端再次发起该请求时,请求头
If-Modified-Since
字段会携带上次请求返回的Last-Modified
值 - 服务器根据
if-modified-since
的值,与该资源在服务器最后被修改时间做对比,若服务器上的时间大于Last-Modified
的值,则重新返回资源,返回 200,表示资源已更新;反之则返回 304,代表资源未更新,可继续使用缓存
- 第一次访问页面时,服务器的响应头会返回
ETag
:当前资源文件的一个唯一标识(由服务器生成),若文件内容发生变化该值就会改变
ETag
的验证流程:
- 第一次访问页面时,服务器的响应头会返回
Etag
字段 - 客户端再次发起该请求时,请求头
If-None-Match
字段会携带上次请求返回的Etag
值 - 服务器根据
If-None-Match
的值,与该资源在服务器的Etag
值做对比,若值发生变化,状态码为 200,表示资源已更新;反之则返回 304,代表资源无更新,可继续使用缓存
为什么要有 Etag ?
Etag
的出现主要是为了解决一些 Last-Modified
难处理的问题:
- 一些文件也许会周期性的更改,但是内容并不改变(仅仅改变的修改时间),这时候并不希望客户端认为这个文件被修改了而重新去请求
- 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说 1s 内修改了 N 次),
If-Modified-Since
能检查到的粒度是秒级的,使用Etag
就能够保证这种需求下客户端在 1 秒内能刷新 N 次cache
注意:Etag 优先级高于 Last-Modified,若 Etag 与 Last-Modified 两者同时存在,服务器优先校验 Etag
协商缓存的两种状态
服务器根据请求头携带的缓存标识,判断该资源是否变化,资源未变化返回 304,反之返回 200
- 资源未变化,返回 304
- 资源已更新,返回 200
协商缓存的流程
- 第一次请求:客户端发送请求,服务器处理请求,返回文件内容和一堆
Header
,包括Etag
和Last-Modified
,状态码 200 - 第二次请求:
- 客户端发起请求,此时请求头上会带上
if-none-match
值为Etag
和if-modified-since
值为last-modified
- 服务器优先判断
Etag
,若资源未变化状态码为 304,客户端继续使用本地缓存,若资源发生变化,状态码为 200 并返回最新的资源
缓存的优点
- 避免数据的冗余请求,节省流量计费
- 减少服务器的负担,提升性能
- 加快浏览器的响应速度,提升用户体验感
总结
提示
浏览器缓存在前端性能优化中占据比较重要的位置,合理使用缓存对项目的性能会有不错的提升。