缓存首先得有个位置放置,共有4个:
service worker
: 浏览器与服务器之间的中间人角色,可以自由控制缓存文件memory cache
:内存缓存,一般用来缓存html页,图片,脚本等disk cache
:硬盘缓存,一般用来缓存大文件,或者csspush cache
: HTTP2产物,以上3种缓存都取不到的时候才能轮到它
主要探讨内存缓存和硬盘缓存
===谁来决定缓存位置===
浏览器
===如何选择缓存位置===
- 对于大文件来说,大概率是不存储在内存中的,反之优先
- 当前系统内存使用率高的话,文件优先存储进硬盘
===缓存优先级===
内存 > 硬盘
===为什么css要放在disk,js要放在memory===
css只需加载一次,js需要频繁读取
===缓存消除===memory cache
在进程结束后就会清除,disk cache
根据过期时间清除
下面将浏览器与服务器之间关于缓存的事情
这里要引出两个概念:强缓存和协商缓存
强缓存:浏览器不发送HTTP请求,直接从缓存中取,比如上一次缓存下来的图片,脚本等
关键字段:
- 状态码200,显示从内存缓存中获取
Expires
:缓存过期时间,HTTP1.0产物,当时间没有过期,就可直接命中缓存。缺点是,客户端时间不一定准确,会造成缓存混乱Cache-Control
: 缓存的持续时间,HTTP1.1产物,优先级大于Expires
,在第一次从服务器请求到该资源后,在缓存的持续时间内再次请求直接命中缓存。它有几个设置值:
no-cache:每次请求需要协商缓存
no-store:禁止使用缓存
协商缓存:当没有命中强缓存后,浏览器会发送一个请求,请求header里面带一些信息,然后服务器判断是否命中缓存, 命中则返回304
浏览器请求header中包含一下字段:
If-Modified-Since
上面强缓存的图里面有一个属性Last-Modified
,这是服务器返回资源时携带的信息,表示该资源的最后修改时间。
于是浏览器将这个值赋给If-Modified-Since
传给服务器,服务器根据该值与服务器中修改这个资源的最后时间对比,如果没有变化,返回304和空响应,如果发生了变化,返回200和响应,而浏览器会把这个新的资源再次缓存缺点:
- 它是以秒为最小计量单位的,如果变化在1秒内完成,无法捕获;
- 如果一个资源在一个周期内修改会原来的样子,它本来是可以使用缓存的,但是因为修改时间的问题,就必须重新请求
If-None-Match
当服务器支持ETag和已经开启了ETag的情况下,返回资源时会在header中携带一个ETag
,表示当前资源的唯一标识
浏览器将ETag
的值赋给If-None-Match
传给服务器,与服务器上该资源的ETag
比对,比对一致则返回304,不一致返回200和响应,并返回新的ETag
===谁控制缓存时间===
服务器
===ETag是如何生成的===
根据算法围绕资源计算出来的,比如
char *mketag(char *s, struct stat *sb)
{
sprintf(s, "%d-%d-%d", sb->st_mtime, sb->st_size, sb->st_ino);
return s;
}
// 根据文件的修改时间,大小,信息生成
nginx
中 etag
由响应头的 Last-Modified
与 Content-Length
表示为十六进制组合而成。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。