jjddrushi 2019-12-09
浏览器缓存是优化网站,提升网站性能的有效方法。
浏览器缓存一般指对服务器返回静态资源(html、js、css文件,图片,数据)在客户端的备份。(不考虑ajax请求)
??基于Chrome浏览器版本 78.0.3904.97(正式版本);firefox默认过期时间都是0,设置其他值也无效。
浏览器缓存策略指的是,先判断是否允许浏览器缓存。
通过HeaderEditor的Chrome插件模拟实现。
1. 请求头字段(Request Header)
/*** Pragma决定是否允许资源缓存;*****/ Pragma: no-cache // 对于index.html只设置这一个字段,就不允许缓存 // 对于js/css文件来说,如果没有设置Cache-Control,根据响应头判断
// ??开发者工具中的Disable Cache开启后,浏览器自动设置 Pragma: no-cache; Cache-Control: no-cache;
2. 响应头字段(Response Header)
该字段默认不添加;
Expires: new Date(...) //GMT格式时间 // 表示允许缓存,且指定了缓存资源的过期时间// 当没有Cache-Control时,该字段起作用,API在过期时间内从缓存取值// 如果响应头中出现Cache-Control,该字段直接被忽略
1. 请求头字段(Request Header)
//指定不允许缓存资源 Cache-Control: no-cache;
只对index.html有效 // 浏览器刷新时,index.html页面自动携带Cache-Control: max-age=0 // 相当于响应头中的Cache-Control: no-cache Cache-Control: max-age=0 // 允许缓存;即时过期,进入协商缓存阶段
其他值测试都无效果
2. 响应头字段(Response Header)
对于静态资源请求,服务器会自动携带Cache-Control: public, max-age=0
对于ajax请求,默认没有Cache-Control字段,需要手动设置
/** Express启动的应用,html, js,css文件默认返回的值;**/ Cache-Control: public,max-age=0 // public: 表示服务器允许客户端,CDN等代理服务器等缓存 // max-age: 允许缓存,并且缓存过期时间是0,下次请求就会进入协商缓存;
Cache-Control: private // 只允许客户端缓存
这个值和请求头中的行为不一致 Cache-Control: no-cache // 允许缓存,立即过期,直接进入协商缓存;
Cache-Control: no-store // 不允许缓存资源;相当于请求头中的no-cache
index.html无效;它即使在过期时间内,也直接执行协商缓存; // js文件有效。再次访问,在缓存过期时间内,直接从内存中获取,状态码200(from memory cache),不会向服务器发起请求;过期后进入协商缓存阶段 Cache-Control: max-age=5 // 5秒 // 允许缓存,并且过期时间距离响应返回时间5秒;5秒内直接从缓存中取值,5秒后请求进入协商缓存
协商策略是在本身有缓存,但是缓存过期后的请求规则。
对于静态资源资源请求,服务器会自动添加对应的字段。
1. Last-Modified(响应头)/If-Modified-Since(请求头)
只能精确到秒,精确度比较低
Last-Modified: Tue, 04 Apr 2017 10:01:15 GMT // GMT时间格式;只能精确到秒 If-Modified-Since: Tue, 04 Apr 2017 10:01:15 GMT // GMT时间格式
1)如果某接口初次加载的时候允许缓存,客户端会将响应头和返回的内容进行缓存。再次请求的时候去缓存区根据缓存的响应头max-age/Expires判断,缓存是否过期;
2)如果没有过期,直接从缓存获取内容,不再向服务器发送请求,对应的状态码200(from memory cache/from dish cache);
3)如果已经过期, 从缓存的响应头中取出Last-Modified的值,赋值给请求头的If-Modified-Since,发起请求,在服务器端将If-Modified-Since的值和被请求资源的Last-Modified比较。
如果相同,则说明资源没有修改,返回304,然后浏览器去缓存区获取内容。如果不同,说明资源已经修改,服务器返回200, 返回最新的资源,更新响应头,并更新缓存区内容。
2. Etag(响应头)/If-None-Match(请求头)
优先级高于Last-Modified,如果共存,会先判断Etag
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4" //唯一标识符号 If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4" ETag: W/"0815" // W/表示弱验证 If-None-Match: W/"0815"
1)同上面第一步,先判断是否过期。
2)如果没有过期,从缓存区返回数据,响应状态码为200(from memory cache/from dish cache)。
3)如果过期,从缓存区响应头取出Etag的值,赋值给请求头If-None-Match字段,向服务器发起请求。在服务器端将If-None-Match和被请求资源的Etag比较。
如果相同,说明资源未改变,服务器返回304,浏览器去缓存区获取资源;如果不同,说明资源修改,返回200,同时更新响应头,返回最新的资源,并更新缓存区内容。
1. 浏览器发起请求,浏览器根据请求头的Pragma/Cache-Control或者响应头Cache-Control来判断,初次请求返回结果是否要进行缓存。
2.如果允许缓存,浏览器将响应头和响应内容全部缓存在客户端。
3. 再次发起请求,浏览器到缓存区根据之前缓存的响应头中Expires/Cache-Control判断缓存是否过期。
4.如果未过期,则直接从缓存区返回内容,并返回状态码200(from memory cache/from dash cache)。如果缓存过期,浏览器向服务器再次发起请求,并携带If-None-Macth/If-Modified-Since字段,两个字段分别对应之前缓存的Etag/Last-Modified字段。
5. 服务器再次接受到请求,根据携带的If-None-Macth/If-Modified-Since字段,分别和服务器端资源的Etag/Last-Modified比较。如果相同,说明资源未经过修改,则只返回响应头,不返回资源内容,响应状态码为304,浏览器接收到304,再到缓存区取出数据,并更新过期时间。如果不相同,说明资源经过了修改,服务器返回200,并返回最新的资源,更新响应头对应的Etag/Last-Modified,再次将新的响应内容进行缓存,更新缓存区的内容,然后将响应内容返回给浏览器。
强制不适用缓存资源。
1. 问题描述:
用户从收藏夹点击进入网站,浏览器加载的index.html文件始终是旧文件。
解决办法:
在服务器端,设置返回index.html文件的响应的时候,响应头设置Cache-Control: no-store不允许缓存或者Cache-Control: max-age=0/no-cache只允许协商缓存。
2. 问题描述:
如果资源文件(js/css等)设置的缓存过期时间特别久,则浏览器会一直从本地缓存资源获取文件,不向服务器发出请求。一直获取不到最新的文件。
解决办法:
1)修改引入文件的文件名(添加hash后缀)
将js/css文件添加hash后缀。对于浏览器来说,文件后缀修改,对于浏览器来说是新的资源,会重新加载资源。
2)给引入文件路由添加时间戳
url+?timeStamp=1323123213, 浏览器也会认为是新的资源