浏览器缓存机制
http缓存指的是: 当客户端向服务器请求资源时,会先抵达浏览器缓存,如果浏览器有“要请求资源”的副本,就可以直接从浏览器缓存中提
取而不是从原始服务器中提取这个资源。
常见的http缓存只能缓存get请求响应的资源
浏览器缓存机制是指通过 HTTP 协议头里的 Cache-Control/Expires和 Last-Modified/Etag等字段来控制文件缓存的机制。
总结
协议 | 缓存有效时间 | 标识位 | 辅助 | 无修改 | 有修改 | 优先级 |
---|---|---|---|---|---|---|
http 1.1 | Cache-Control中的max-age | Last-Modified标识文件在服务器上的最新更新时间 | If-Modified-Since | 返回304,继续使用缓存 | 返回200,同时返回最新的文件 | |
Etag 对文件进行标识的特征字串 | If-None-Match | 返回304,继续使用缓存 | 返回200,同时返回最新的文件 | 高 | ||
http 1.0 | Expires 绝对的时间点 | 低 |
情况 | 浏览器操作 | 请求字段 |
---|---|---|
手动刷新 F5 | 认为缓存已经过期(可能缓存还没有过期) | Cache-Control:max-age=0 |
强制刷新 Ctrl+F5 | 忽略本地的缓存(有缓存也会认为本地没有缓存) | Cache-Control:no-cache (或 Pragma:no-cache 兼容HTTP1.0) |
状态码 | 条件 | 服务器变化与否 |
---|---|---|
200(from cache) | expires/cache-control 没失效 | 无变化 |
304 | last-modified/etag 失效 、F5、点击刷新 | 无变化 |
200 | 本地无缓存、last-modified/etag 失效、 ctrl + F5 | 有变化 |
为什么有了Last-Modified ,还需要Etag?
Last-Modified:
- 修改精确到秒,1s内的改变不能标记
- 文件定期生成但内容不变,Last-Modified改变了,会导致不用缓存
- 当与代理服务器时间不一致时,会出问题
Etag:
- 服务器自动生成 / 开发者生成
- 对应着资源在服务器端的唯一标识符
- 更加准确的控制缓存
- 服务器会优先验证Etag
- Yahoo建议分布式系统尽量关闭掉Etag
缓存分类
https://www.jianshu.com/p/227cee9c8d15
根据是否可以被单个或者多个用户使用来分类:
-
私有缓存(浏览器级缓存)
- 私有缓存只能用于单独的用户:
Cache-Control: Private
- 私有缓存只能用于单独的用户:
-
共享缓存(代理级缓存)
- 共享缓存可以被多个用户使用:
Cache-Control: Public
- 共享缓存可以被多个用户使用:
根据是否需要重新向服务器发起请求来分类,可分为(强制缓存,协商缓存)
强缓存 | 协商缓存 | |
---|---|---|
存放位置 | 本地浏览器 | 本地浏览器 |
状态码 | 200 | 304 |
决定因素 | Pragma Cache-Control Expires | ETag/If-None-Match Last-Modified/If-Modified-Since |
是否与服务器交互 | 否 | 是 |
操作是否有效 | 强制刷新与F5刷新 – 无效; 地址栏回车、页面链接跳转、新开窗口、前进/后退 – 有效 | 强制刷新 – 无效; F5刷新 – 有效 地址栏回车、页面链接跳转、新开窗口、前进/后退 – 有效 |
在chrome浏览器中返回的200状态会有两种情况:
-
1、from memory cache (从内存中获取/一般缓存更新频率较高的js、图片、字体等资源)
-
2、from disk cache (从磁盘中获取/一般缓存更新频率较低的js、css等资源)
这两种情况是chrome自身的一种缓存策略,这也是为什么chrome浏览器响应的快的原因。其他浏览返回的是已缓存状态,没有标识是从哪获取的缓存。
详解
-
Cache-Control 控制文件在本地缓存有效时长。服务器响应标头
cache-control: no-cache, no-store, max-age=0, must-revalidate
中的max-age表示时长,单位:秒 -
Last-Modified 标识文件在服务器上的最新更新时间
- 下次请求时,如果文件缓存过期,浏览器通过 If-Modified-Since 字段带上这个时间,发送给服务器,由服务器比较时间戳来判断文件是否有修改。
- 如果没有修改,服务器返回304告诉浏览器继续使用缓存
- 如果有修改,则返回200,同时返回最新的文件
Cache-Control 通常与 Last-Modified 一起使用。一个用于控制缓存有效时间,一个在缓存失效后,向服务查询是否有更新。
-
Expires 与Cache-Control 同功能。Expires 的值是一个绝对的时间点,如:Expires: Thu, 10 Nov 2015 08:45:11 GMT,表示在这个时间点之前,缓存都是有效的。若客户端与服务器相差时间大,误差会很大
Expires 是 HTTP1.0 标准中的字段,Cache-Control 是 HTTP1.1 标准中新加的字段,功能一样,都是控制缓存的有效时间。当这两个字段同时出现时,Cache-Control 是高优化级的。
-
Etag 也是和 Last-Modified 一样,对文件进行标识的字段。不同的是,Etag 的取值是一个对文件进行标识的特征字串。
- 在向服务器查询文件是否有更新时,浏览器通过 If-None-Match 字段把特征字串发送给服务器,由服务器和文件最新特征字串进行匹配,来判断文件是否有更新。
- 没有更新回包304
- 有更新回包200
Etag 和 Last-Modified 可根据需求使用一个或两个同时使用。两个同时使用时,只要满足基中一个条件,就认为文件没有更新。
怎么使用缓存
一般需要缓存的资源有html页面和其他静态资源:
-
1、html页面缓存的设置主要是在标签中嵌入标签,这种方式只对页面有效,对页面上的资源无效
- 1.1、html页面禁用缓存的设置如下:
// 仅有IE浏览器才识别的标签,不一定会在请求字段加上Pragma,但的确会让当前页面每次都发新请求 <meta http-equiv="pragma" content="no-cache"> // 其他主流浏览器识别的标签 <meta http-equiv="cache-control" content="no-cache"> // 仅有IE浏览器才识别的标签,该方式仅仅作为知会IE缓存时间的标记,你并不能在请求或响应报文中找到Expires字段 <meta http-equiv="expires" content="0">
- 1.2、html设置缓存如下:
<meta http-equiv="Cache-Control" content="max-age=7200" /> // 其他主流浏览器识别的标签 <meta http-equiv="Expires" content="Mon, 20 Aug 2018 23:00:00 GMT" /> // 仅有IE浏览器才识别的标签
-
2、静态资源的缓存一般是在web服务器上配置的,常用的web服务器有:nginx、apache
浏览器请求流程图
浏览器第一次请求:
浏览器再次请求时:
Cookie与webStorage区别
总结
类型 | 数据存储地址 | 生命周期 | 存储的数据量 | 作用域 | 其他 |
---|---|---|---|---|---|
cookie | http的同源请求中 | 设置的过期时间expires | 4k | 同源浏览器(相同的协议、相同的主机名、相同的端口) | 在客户端与服务器端回传 |
localStorage | 本地浏览器 | 永久,除非手动清除 | 5M或更多(跟浏览器类型有关) | 同源浏览器 | 可指定路径,支持事件通知机制,只能存储获取String类型的数据(JSON.stringify()、JSON.parse()) |
sessionStorage | 本地浏览器 | 当次会话,结束后被清除 | 5M | 同一次会话(相同的协议、相同的主机名、相同的端口、同一窗口) | 支持事件通知机制,只能存储获取String类型的数据(JSON.stringify()、JSON.parse()) |
详解
-
数据存储
- cookie的数据始终在http的同源请求中存储,数据可以在客户端与服务器端进行回传。
- webStorage的数据只能进行本地存储,不能向服务器进行传递。
-
生命周期
- sessionStorage 会话级别的缓存,在当次会话结束后缓存数据被清除
- localStorage 永久缓存,直到被手动清除
- cookie 可以设置声明周期,到该时间失效
-
存储的数据量
- 每次http的请求都会携带cookie,所以 cookie存储数据的大小要求不能超过 4k
- webStorage 数据因为只在本地进行缓存,对数据存储量的可以达到 4-5M
-
作用域
- sessionStorage 作用在同一次会话之间,不在不同浏览器及同源之间进行共享。除了协议、主机名、端口外,还要求在同一窗口(也就是浏览器的标签页)下
- localStorage 作用在同源浏览器之间,只要在相同的协议、相同的主机名、相同的端口下,就能读取/修改到同一份localStorage数据
- cookie 作用域也是在同源浏览器之间
-
cookie的数据还有路径的概念,可以通过设置限制cookie只属于某个路径
-
可以使用 path 参数告诉浏览器 cookie 的路径。默认情况下,cookie 属于当前页面
document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";
-
-
webstorage 支持事件通知机制,可以将数据更新的通知发送给监听者
-
window.addEventListener(“storage”,doReaction,flag);
-
storage:表示对Storage(包括Localstorage和sessionStorage)进行监听
-
doReaction:自定义函数,事件发生时回调,会接收一个StorageEvent类型的参数,包括:
- storageArea
- key(发生变化的key)
- oldValue(原值)
- newValue(新值)
- url(引发变化的URL)
-
flag:表示触发时机,一般多使用false
-
function doStart(){
window.addEventListener("storage",callback,false);
}
function callback(se){
console.log("被修改的key:"+se.key);
console.log("原值:"+se.oldValue);
console.log("新值:"+se.newValue);
console.log("url地址:"+se.url);
if(se.key=="token"){
console.log("token已被修改!");
}
}
webStorage 特点
webStorage好处 | webStorage方法 | 方法解读 |
---|---|---|
减少网络流量 | setItem(key, value) | 设置存储内容 |
快速显示数据 | getItem(key) | 读取存储内容,获取到的数据都是String类型 |
临时存储 | removeItem(key) | 删除键值为key的存储内容 |
不影响网络效能 | clear() | 清空所有存储内容 |
-
webStorage 的好处
-
1、减少网络流量:使用webstorage将数据保存在本地中,减少不必要的请求
-
2、快速显示数据:从本地获取数据比通过网络从服务器获取数据效率更高,因此网页显示也比较快
-
3、临时存储:很多时候数据只需在用户浏览一组页面期间使用,关闭窗口后数据就会丢失,使用sessionstorage 比较方便
-
4、不影响网络效能:因为webstorage只作用在客户端的浏览器,不会占用频宽
-
离线应用 manifest
HTML5中我们可以轻松的构建一个离线(无网络状态)应用,只需要创建一个cache manifest文件。
-
优势
- 1、可配置需要缓存的资源
- 2、网络无连接应用仍可用
- 3、本地读取缓存资源,提升访问速度,增强用户体验
- 4、减少请求,缓解服务器负担
-
缓存清单
- 一个普通文本文件,其中列出了浏览器应缓存以供离线访问的资源,推荐使用.appcache为后缀名
- 例如我们创建了一个名为demo.appcache的文件,然后在需要应用缓存在页面的根元素(html)添加属性
manifest="demo.appcache"
,路径要保证正确。
-
manifest文件格式
- 1、首行必须是CACHE MANIFEST
- 2、每一行列出一个需要缓存的资源文件名。
- 3、NETWORK: 换行 白名单中的所有资源不会被缓存,在使用时将直接在线访问,可使用通配符
- 4、CACHE: 换行 在白名单后还要补充需要缓存的资源,如.css、image、js等
- 5、FALLBACK: 换行 当被缓存的文件找不到时的备用资源
-
其它
- 1、CACHE: 可以省略,这种情况下将需要缓存的资源写在CACHE MANIFEST
- 2、可以指定多个CACHE: NETWORK: FALLBACK:,无顺序限制
- 3、注释要另起一行,#表示注释,只有当demo.appcache文件内容发生改变时或者手动清除缓存后,才会重新缓存。
- 4、chrome 可以通过chrome://appcache-internals/工具和离线(offline)模式来调试管理应用缓存
CACHE MANIFEST
# 上一行必须写
# 两个png图片必须缓存
images/sound-icon.png
images/background.png
# 不会被缓存
NETWORK:
comm.cgi
# 下面是另一些需要缓存的资源,在这个示例中只有一个 css 文件。
CACHE:
style/default.css
# 当第一个 URI 不可访问时,浏览器将尝试使用第二个 URI
FALLBACK:
/files/projects /projects
html页面引入上面的manifest文件:
<!DOCTYPE HTML>
<html manifest="calender.manifest">
<head>...</head>
<body>...</body>
</html>
1、自动更新
cache manifest 文件本身发生变化时更新缓存,,而 cache manifest 中的 资源文件 发生变化并不会触发更新。
2、手动更新
使用 window.applicationCache 的接口 手动更新缓存:
if(window.applicationCache.status == window.applicationCache.UPDATEREADY) {
window.applicationCache.update();
}