前端er须要关注的点:缓存前端
这真是一个令开发者又爱又恨的东西
现代手机随时随地会缓存你的资源,可是要想清缓存,不能像PC使用强制刷新,你须要手动清理浏览器缓存,甚至有时候还要重启...
因此理解缓存机制并可以掌控它就显的相当重要(比较牛逼了)npm
下面咱们将先通读理论而后结合实践真正理解缓存机制浏览器
全称 Domain Name System
域名解析系统
它的做用很是简单,就是根据域名查出IP地址缓存
简单的说,经过域名最终解析到该域名对应的IP地址bash
www.dnscache.com (域名) - DNS解析 -> 11.222.33.444 (IP地址)
复制代码
有DNS的地方,就有缓存! 浏览器、操做系统、Local DNS、根域名服务器,它们都会对DNS结果作必定程度的缓存服务器
全称 Content Delivery Network,即内容分发网络。 相似于火车站代售点,乘客不用再去售票大厅去排队买票 减轻了售票大厅的压力(起到分流做用,减轻服务器负载压力)网络
用户在浏览网站的时候,CDN
会选择一个离用户最近的CDN边缘节点来响应用户的请求,这样海南移动用户的请求就不会千里迢迢跑到北京电信机房的服务器(假设源站部署在北京电信机房)上了app
当浏览器本地缓存失效,浏览器会向CDN边缘节点发起请求。相似浏览器缓存,CDN边缘节点也存在着一套缓存机制
koa
CDN边缘节点缓存策略因服务商不一样而不一样,但通常都会遵循http
标准协议,经过http响应头中的 Cache-control: max-age
的字段来设置CDN边缘节点数据缓存时间。async
CDN边缘节点数据缓存机制
CDN服务商通常会提供基于文件后缀、目录多个维度来指定CDN缓存时间,为用户提供更精细化的缓存管理。
盯着这张图
你可能会有疑问,浏览器存储了资源,那它把资源存储在哪里呢?
MemoryCache顾名思义,就是将资源缓存到内存中,等待下次访问时不须要从新下载资源,而直接从内存中获取。Webkit早已支持memoryCache。
目前Webkit资源分红两类,一类是主资源,好比HTML页面,或者下载项,一类是派生资源,好比HTML页面中内嵌的图片或者脚本连接,分别对应代码中两个类:MainResourceLoader和SubresourceLoader。虽然Webkit支持memoryCache,可是也只是针对派生资源,它对应的类为CachedResource,用于保存原始数据(好比CSS,JS等),以及解码过的图片数据。
复制代码
DiskCache顾名思义,就是将资源缓存到磁盘中,等待下次访问时不须要从新下载资源,而直接从磁盘中获取,它的直接操做对象为CurlCacheManager。
复制代码
须要说明的是 浏览器会先判断是否命中强缓存
浏览器在第一次请求发生后,再次请求时:
强缓存是利用http的返回头中的Expires
或者Cache-Control
两个字段来控制的,用来表示资源的缓存时间。
Expires: 该字段是http1.0时的规范,它的值为一个绝对时间的GMT格式的时间字符串,好比Expires:Mon,18 Oct 2066 23:59:59 GMT。这个时间表明着这个资源的失效时间,在此时间以前即命中缓存
缺点:
Cache-Control: Cache-Control是http1.1时出现的header信息,主要是利用该字段的max-age值来进行判断,它是一个相对时间,例如Cache-Control:max-age=3600,表明着资源的有效期是3600秒。cache-control除了该字段外,还有下面几个比较经常使用的设置值:
Cache-Control与Expires能够在服务端配置同时启用,同时启用优先级 Cache-Control > Expires
当强缓存没有命中的时候,浏览器会发送一个请求到服务器,服务器根据 header
中的部分信息来判断是否命中缓存。若是命中,则返回304
,告诉浏览器资源未更新,可以使用本地的缓存。
header: `Last-Modify/If-Modify-Since `和 `ETag/If-None-Match`
复制代码
Last-Modify/If-Modify-Since:浏览器第一次请求一个资源的时候,服务器返回的 header 中会加上 Last-Modify,Last-modify 是一个时间标识该资源的最后修改时间。 当浏览器再次请求该资源时,request 的请求头中会包含 If-Modify-Since,该值为缓存以前返回的 Last-Modify。服务器收到 If-Modify-Since 后,根据资源的最后修改时间判断是否命中缓存。 若是命中缓存,则返回 304,而且不会返回资源内容,而且不会返回 Last-Modify。
缺点:
Last-Modified
并不会发生变化。Last-Modified
可不这样认为,所以便有了 ETag
ETag/If-None-Match
与 Last-Modify/If-Modify-Since
不一样的是,Etag/If-None-Match
返回的是一个校验码。ETag
能够保证每个资源是惟一的,资源变化都会致使 ETag
变化。服务器根据浏览器上送的 If-None-Match
值来判断是否命中缓存。 与 Last-Modified
不同的是,当服务器返回 304 Not Modified
的响应时,因为 ETag
从新生成过,response header
中还会把这个 ETag
返回,即便这个 ETag
跟以前的没有变化。
Last-Modified 与 ETag 是能够一块儿使用的,服务器会优先验证 ETag,一致的状况下,才会继续比对 Last-Modified,最后才决定是否返回 304。
我讨厌文字记忆,因此坚决果断选了理工科~~ talk is cheap , show me your code
⚠️ 实践过程控制台不要禁用缓存
利用koa
启动server
服务 port:8000
引入静态资源 加载前端模版 去内蒙的航拍 哈哈哈 有我
cache
与图片资源
1.jpeg
实现强缓存
app.use(async (ctx, next) => {
ctx.set({
'Cache-Control': 'max-age=300'
});
await next();
});
复制代码
Cache-Control
变成了 max-age=300
验证访问缓存的优先级: 第一次的网络请求,浏览器把图片资源缓存到了磁盘和内存里,根据约定 应该会先从内存中找资源
确实是从内存获取的
4.关掉页面再从新打开 (内存是存在进程中的,因此关闭该页面,内存中的资源也被释放掉了,磁盘中的资源是永久性的,因此还存在)
from disk cache 从磁盘中获取资源
5.接下来 有效期 300秒 后.
实现协商缓存 协商缓存本地测试直接拦截url给定code
Cache-Control 取默认值 no-cache
app.use( async(ctx, next) => {
// 协商缓存测试
if(ctx.url === '/imgs/1.jpeg'){
ctx.status = 304;
return;
}
await next();
});
复制代码
服务器返回304
同时size
变小了不少 由于只返回了必要信息
也可利用现成的插件帮咱们计算文件的ETag
npm install koa-tag -D
npm install koa-conditional-get -D
复制代码
具体细节不演示了
经测试发现当加载资源发生变化时(好比换了张图片),ETag
改变了进而协商缓存策略失效了
day day up !