浏览器缓存
前言
浏览器缓存又叫客户端缓存,存储在客户端的缓存,由浏览器控制,关于存储的策略由响应头(Response Header)规定,主要的响应头标记是Cache-Contro、Etag、Last-Modified.
生效范围:
仅对当前浏览器生效。
实现方式:
使用HTTP Header
更新策略:
Time-ETag-Version 如:max-age:60 设定缓存60秒 xxx.js?version=v1 xxx.css?version=v1 改变css,js请求地址即可重新请求css,js文件,也就是只要改变version即可
客户端缓存相关
- Etag是个MD5摘,由服务器发送给客户端的一串字符,用来资源是否发生改变。
- If-None-Match是在Etag存在的情况下请求服务器时发送给服务器用来校验资源的哈希值,当客户端发送的摘要与服务器的不同则重新请求,返回200,相同则返回304使用本地存储的资源;如:If-None-Match: "3f80f-1b6-3e1cb03b",3f80f-1b6-3e1cb03b是Etag
- Last-Modified是资源最后修改时间,用来与服务器对比检验资源是否发生改变。
- If-Modified-Since是在Last-Modified存在时,将Last-Modified发送给服务器,服务器端的资源最后修改时间与浏览器发送过来的对比,相同返回304使用本地存储的资源,否则返回200重新请求资源.
Cache-Contro
- no-store:彻底禁用缓冲,所有内容都不会被缓存到缓存或临时文件中,如果已经存在还是会加载。
- no-cache:在浏览器使用缓存前,会往返对比ETag,如果ETag没变,返回304,则使用缓存,no-cache不代表不存储缓存,只是存储而不直接使用,必须先和服务器做对比然后才决定要不要使用,没有直接使用磁盘缓存快,但是比在服务器请求资源快。 public 所有内容都将被缓存(客户端和代理服务器都可缓存)。
- private:内容只缓存到私有缓存中(仅客户端可以缓存,代理服务器不可缓存)。
- max-age:缓存的内容将在 xxx 秒后失效,这个选项只在HTTP1.1可用,并如果和Last-Modified一起使用时,优先级较高。
客户端缓存流程
先上一张缓存流程图
图解:当客户端发起请求,第一步会先检查缓存是否过期,没过期直接读取缓存(一些资源浏览器都会存储在内存中,第二次请求时返回200 memory cache),当内存中存储没了会使用磁盘中的缓存文件返回200(disk cache)。如果已过期浏览器将向判断是否存在Etag,存在的话服务器发送If-None-Match:第一次请求获得的Etag,服务器拿到该Etag对比是否改变,如果没变如果资源为改变返回304HTTP状态码,否则从新请求返回200HTTP状态码。当不存在Etag时,查看是否存在Last-Modified(最后修改时间),存在的话走向web服务器请求带If-Modfied-Since路线,If-Modified-Since把浏览器缓存页面的最后修改时间发送给服务器做对比,如果时间一致则返回304HTTP状态码,直接从本地获取资源,否则返回200HTTP状态码重新请求。如果Etag不存在,Last-Modified不存在直接向服务器发送请求。
使用缓存时,状态码会返回200或者304,当返回200时Size为disk cache或者memory cache,都是在客户端存储着,所以并没有像服务器请求,直接获取客户端缓存; 当服务端和客户端都存在缓存,客户端缓存过期后再去请求服务器会带Etag和Last-Modified,如果资源没有改变返回304
示例
在.net core3.1中使用:
MVC控制器使用缓存,使用特性或者在响应头中使用cache-control
[ResponseCache(Duration = 7200, Location = ResponseCacheLocation.Any)] public class testController : Controller { public IActionResult Index() { var time = DateTime.Now.ToString(); ViewBag.Current = time; //base.HttpContext.Response.Headers["Cache-control"] = "no-cache"; return View(); } }
Startup中制定静态文件缓存策略
app.UseStaticFiles(new StaticFileOptions { FileProvider=new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(),@"wwwroot")), OnPrepareResponse = ctx => { //ctx.Context.Response.Headers[HeaderNames.CacheControl] = "no-cache"; ctx.Context.Response.Headers[HeaderNames.CacheControl] = "no-cache, max-age=0, must-revalidate"; } });
注意:由于浏览器会自动缓存静态文件,所以不好测试;不同的浏览器不同的缓存流程,缓存也不一样,只要请求到了就会自动缓存,第二次请求如果在同一个tab会返回200(memory cache),这是由于在内存缓存中加载的结果;如果在不同tab那么memory cache不存在,于是会从磁盘读取缓存,返回200(disk cache);当设置的响应cache-control为no-cache时正常情况下第二次请求会返回304,按照上图中流程,走的是Etag路线=》服务器决策=》304;
网络请求
第一次请求与第二次请求结果
第一次网络请求,所有资源都是从服务器请求过来的
第二次网络请求,所有资源都被缓存在磁盘,如果在同一个页面请求时(memory cache),否则如下图
通过使用不同的cache-control可以控制缓存策略,按照自己所需的实际情况配置。