当前位置: 首页 > 科技观察

前端必须了解的浏览器缓存机制

时间:2023-03-19 01:43:59 科技观察

1.什么是浏览器缓存?浏览器通常会在您的PC磁盘和内存中缓存经常使用的资源。例如Chrome浏览器的缓存存放位置在\Users\Your_Account\AppData\Local\Google\Chrome\UserData\Default中的Cache文件夹和MediaCache文件夹。2、什么是静态资源服务器?一般的网站,静态资源使用频率高,流量占用大。对于访问量比较大的网站,静态资源会放在CDN服务器上,不会占用业务服务器的网络带宽,达到更好的用户体验。3、浏览器请求静态资源的过程对于前端开发者来说,我们主要是处理浏览器中的缓存。上图中的流程是一个简化版;事实上,在实际应用中通常使用静态资源服务器(CDN)。4、浏览器端缓存的分类下图是一个网站对不同资源的请求结果。可以看到有的资源是直接从缓存中读取的,有的资源是和服务器重新认证过的,有的资源是从服务器重新获取的。200fromcache304notmodified请注意,我们讨论的关于缓存资源的所有问题仅针对GET请求。对于POST、DELETE和PUT等行为操作,通常没有缓存。5、Cache-Control和ExpiresCache-Control是HTTP1.1中新增的响应头。Expires是HTTP1.0中的一个响应头。Cache-Control使用相对时间。Expires指定特定的到期日期而不是秒数。因为很多服务器和客户端存在时钟不一致的情况,所以最好使用Cache-Control。如果同时使用Cache-Control和Expires,Cache-Control会覆盖Expires6。Cache-Control可以设置哪些属性max-age(单位是s)指定设置缓存***的有效时间,定义了时间长度。浏览器向服务器发送请求后,浏览器在max-age时间内不会再向服务器发送请求。public指定响应可以缓存在代理缓存中,因此可以由多个用户共享。如果未明确指定私有,则默认为公共。私有响应只能缓存在私有缓存中,不能缓存在代理缓存中。对某些用户信息敏感的资源通常需要设置为私有。no-cache的意思是首先要和服务器确认资源是否发生变化(取决于If-None-Match和Etag),然后再决定是否使用本地缓存。no-store绝对禁止缓存任何资源,也就是说用户每请求一个资源,都会向服务器发送一个请求,每次都会下载完整的资源。通常用于机密资源。关于Cache-Control的使用,见下图7。新鲜度限制HTTP通过缓存在一段时间内保留一份服务器资源副本,这段时间称为新鲜度限制。这个对同一个资源的请求在一段时间内不会再经过服务器。HTTP协议中的Cache-Control和Expires可以用来设置新鲜度限制。前者是HTTP1.1中新增的响应头,后者是HTTP1.0中的响应头。两者做的是一样的,但是因为Cache-Control使用的是相对时间,而Expires可能会存在客户端和服务端时间不同的问题,所以我们更倾向于选择Cache-Control。html代码网络缓存node服务端代码varhttp=require('http');varfs=require('fs');http.createServer(function(req,res){if(req.url==='/'||req.url===''||req.url==='/index.html'){fs.readFile('./index.html',function(err,file){控制台。log(req.url)//对主文件设置保存,无效res.setHeader('Cache-Control',"no-cache,max-age="+5);res.setHeader('Content-Type','text/html');res.writeHead('200',"OK");res.end(文件);});}if(req.url==='/cache.png'){fs.readFile('./cache.png',function(err,file){res.setHeader('缓存控制',"max-age="+5);//缓存五秒res.setHeader('Content-Type','images/png');res.writeHead('200',"NotModified");res.end(file);});}}).listen(8888);5秒内第二次访问页面时,浏览器会直接从缓存中获取资源8.服务器会校验缓存中的信息browserorproxycache当一个资源过期时,并不意味着它实际上与原来服务器上的资源不同,只是意味着该检查了。这种情况称为服务器重新验证。如果资源发生变化,则需要获取一个新的资源,并替换缓存中的旧资源。如果资源没有变化,缓存只需要获取一个新的响应头和一个newexpirationtime更新缓存中的资源过期时间。HTTP1.1推荐验证方式为If-None-Match/Etag,HTTP1.0中使用If-Modified-Since/Last-Modified。9.Etag和If-None-MatchEtag指的是根据实体的内容生成一个hash字符串来标识资源的状态,由服务器生成。浏览器会将这个字符串发回服务器,以验证资源是否被修改。如果没有,流程如下:代码示例varhttp=require('http');varfs=require('fs');http.createServer(function(req,res){if(req.url==='/'||req.url===''||req.url==='/index.html'){fs.readFile('./index.html',function(err,file){控制台。log(req.url)//为主文档设置缓存,无效res.setHeader('Cache-Control',"no-cache,max-age="+5);res.setHeader('Content-Type','text/html');res.writeHead('200',"OK");res.end(file);});}if(req.url==='/shortcut.png'){fs.readFile('./shortcut.png',function(err,file){console.log(req.url)res.setHeader('Content-Type','images/png');res.writeHead('200',"OK");res.end(file);})}if(req.url==='/cache.png'){fs.readFile('./cache.png',function(err,file){console.log(req.headers);console.log(req.url)if(!req.headers['if-none-match']){res.setHeader('Cache-Control',"max-age="+5);res.setHeader('Content-Type','images/png');res.setHeader('Etag',"ffff");res.writeHead('200',"未修改");res.end(文件);}else{if(req.headers['if-none-match']==='ffff'){res.writeHead('304',"NotModified");重发();}else{res.setHeader('Cache-Control',"max-age="+5);res.setHeader('Content-Type','images/png');res.setHeader('Etag',"ffff");res.writeHead('200',"未修改");res.end(文件);}}});}}).listen(8888)10.如何计算Etag值ETag值通常由服务端计算计算,返回给客户端响应客户端请求。通过时间戳最容易获取ETag头信息;但是不建议这样做,它和Last-Modified头信息没什么区别。ETag值可以是唯一标识一个资源的任何东西,比如持久化存储中资源关联的版本、一个或多个文件属性、实体头信息和校验和(CheckSum),实体信息的哈希值可以也要计算。有时,计算ETag值的成本可能相对较高。这时候可以使用生成唯一值(比如普通的GUID)等方法。默认情况下,Apache通过FileEtag中FileEtagINodeMtimeSize的配置自动生成ETag(当然用户也可以自定义)。由于Etag是由服务器构建的,因此在集群环境下必须保证Etag的唯一性。11.If-Modified-Since和Last-Modified是HTTP1.0中用来验证资源是否过期的请求/响应头。两个header都是日期,验证过程和Etag类似,这里不再赘述。在使用这两个头部来验证资源是否更新时,存在以下问题:一些文档资源被定期重写,但实际内容没有改变。这时候文件元数据会显示文件的最新修改日期和If-Modified-Since不一样,导致不必要的响应。修改了一些文档资源,但是修改的内容不重要,所有的缓存都不需要更新(比如代码注释)12.总结浏览器端缓存分为200来自缓存和304未修改HTTP协议Cache-Control和Expires可以用来设置新鲜度限制,前者是HTTP1.1中新的响应头,后者是HTTP1.0中的响应头。max-age(单位是s)和Expires指定一个具体的到期日期而不是秒。如果同时使用Cache-Control和Expires,Cache-Control会覆盖Expires。客户端不需要关心ETag值是如何产生的,只要服务在资源状态发生变化的情况下,发送ETag值给它即可。默认情况下,Apache通过FileEtag中FileEtagINodeMtimeSize的配置自动生成一个ETag(当然用户也可以自定义)。ETag常与If-None-Match或If-Match一起使用,由客户端通过HTTP头信息(包括ETag值)发送给服务器进行处理。Last-Modified常与If-Modified-Since一起被客户端使用,将Last-Modified值包含在HTTP头信息中,发送给服务器处理。一些文档资源会定期重写而不更改实际内容。这时候文件元数据会显示文件的最新修改日期和If-Modified-Since不一样,导致不必要的响应。13演示