分类前端缓存分为强缓存和协商缓存两种。强缓存强缓存主要使用Expires和Cache-Control两个头域,两者同时存在时Cache-Control优先级高。当命中强缓存时,客户端会直接从缓存中读取内容,不再请求,返回HTTP状态码200。Expires响应头,表示资源的过期时间。是GMT格式的标准时间。当客户端向服务器发起请求时,服务器会返回带有响应头Expires的资源,指明资源过期的具体时间。如果客户端在过期时间之前再次获取资源,则不需要再次请求我的服务器。可以直接在缓存中取。使用Expires强缓存的好处:在过期时间内,为用户节省了大量的流量。减轻服务器重复读取磁盘文件的压力。使用Expires强缓存的缺点缓存过期后,无论文件是否发生变化,服务器都会再次请求服务器。缓存过期时间是一个具体的时间,取决于客户端的时间。如果时间不准确或更改,缓存将受到相应影响。Cache-Control请求/响应头,缓存控制字段,缓存策略精准控制。为了让强缓存更准确,HTTP1.1增加了Cache-Control字段。Cache-Control既可以出现在请求头中,也可以出现在响应头中,其不同的值代表不同的含义。下面我们详细分析一下。Cache-Control服务器参数:max-age:多少秒有效,是一个相对时间,比Expires的具体时间更准确。s-maxage:用于表示缓存在缓存服务器(如缓存CDN、缓存代理服务器)上的有效时间,仅对公共缓存有效。no-cache:不使用本地强缓存。需要使用缓存协商。no-store:直接禁止浏览器缓存数据。用户每次请求资源时,都会向服务器发送一个请求,每次都会下载完整的资源。public:可以被所有用户缓存,包括终端用户和中间代理服务器。private:只能被终端用户浏览器缓存,不允许中间缓存代理缓存,默认。Cache-Control客户端参数:max-stale:5表示当客户端从代理服务器获取缓存时,即使代理缓存过期也没有关系,只要过期时间在5秒以内,仍然可以从代理中获取。min-fresh:5表示代理缓存需要一定的新鲜度。不要等到缓存过期了才去获取。必须在过期时间前5秒领取,否则拿不到。增加only-if-cached字段表示客户端只接受代理缓存,不接受源服务器的响应。如果代理缓存失效,直接返回504(GatewayTimeout)。NegotiationCache协商缓存主要有四个头域,成对组合使用,一组If-Modified-Since和Last-Modified,一组Etag和If-None-Match,当它们同时存在时,它们将与Etag结合,而If-None-Match是主要的。当命中协商缓存时,服务器将返回HTTP状态码304,允许客户端直接从本地缓存中读取文件。If-Modified-Since请求头,资源的最新修改时间,由浏览器告知服务器。其实就是服务器第一次返回的Last-Modified的值。Last-Modified响应头,资源的最后修改时间,由服务器告诉浏览器。Etag响应头,资源标识,服务器告诉浏览器的。If-None-Match请求头,缓存资源标识,由浏览器告诉服务器。其实就是第一次访问服务器返回的Etag的值。If-Modified-Since和Last-Modified当客户端第一次请求服务器时,服务器会返回一个Last-Modified响应头,这是一个标准时间。客户端请求服务器时,会带上If-Modified-Since请求头字段,该字段的值为服务器返回的Last-Modified值。服务端收到请求后会比较两个值是否相同,如果相同则返回304,让客户端从缓存中读取,如果不相同则返回一个新的文件给客户端并更新值Last-Modified响应头域。使用If-Modified-Since和Last-Modified的优点:当缓存有效时,服务器不会将文件返回给客户端,而是直接返回一个304状态码,让客户端从缓存中获取文件。大大节省流量和带宽,减轻服务器压力。使用If-Modified-Since和Last-Modified的缺点:Last-Modified过期时间只能精确到秒。如果同时修改和获取文件,客户端将无法获取到最新的文件。Etag和If-None-Match为了解决文件修改时间只能精确到秒的问题,我们引入了Etag响应头。Etag是根据文件修改时间和文件大小计算出来的,Etag的值只会在文件内容或修改时间发生变化时发生变化。当客户端第一次请求服务器时,服务器会返回一个Etag响应头。客户端请求服务器时,会带上If-None-Match请求头字段,该字段的值就是服务器返回的Etag的值。服务端收到请求后会比较这两个值是否相同,如果相同则返回304让客户端从缓存中读取。如果不一样,它会返回一个新的文件给客户端,并更新Etag响应头域的值。使用Etag和If-None-Match的好处:当缓存有效时,服务器不会将文件返回给客户端,而是直接返回一个304状态码,让客户端从缓存中获取文件。大大节省流量和带宽,减轻服务器压力。并在一秒内解决修改读取问题。扩展缓存失效问题缓存的引入是个好东西,可以大大提高响应速度,减轻服务器的压力,但是也会有一些问题,比如我们更新了为什么客户端看到的还是老文件系统版本。不同的时代有不同的解决方法。老方案老方案是手动修改文件名或者在文件名后加上版本号和时间戳,这样客户端会作为新文件来请求使用,之前的强缓存即使在有效期。复制代码的新方案在当前构建阶段基本不需要手动操作,全部使用Wbpack和Gulp,Grunt等构建工具,例如使用Webpack构建时,会根据文件名或文件内容自动计算hash值来命名文件,当内容或文件名发生变化时,构建的文件名会也改了,不一样,这也解决了强缓存仍然有效的问题。cache,表示禁用缓存,优先级为pragma>cache-control>expires,通过这张流程图,大家可以理解的更清楚,如果我们使用Nginx作为web服务器,可以进行如下配置。location/{#其他配置...if($request_uri~*.*[.](js|css|map|jpg|png|svg|ico)$){#非html缓存1个月add_headerCache-Control“公共,最大年龄=2592000”;}if($request_filename~*^.*[.](html|htm)$){#html文件使用协商缓存add_headerCache-Control"public,no-cache";}}复制代码缓存在哪里?很多朋友会好奇,这个缓存存在哪里呢?别担心,让我们继续前进。根据缓存位置,我们可以分为三类:内存缓存、磁盘缓存和ServiceWorker。我们可以在Chrome的开发者工具的Network->Size一栏看到一个请求的最终处理方式:如果是size(多少K,多少M等)就说明是网络请求,否则会listfrommemorycache,fromdiskcache,fromServiceWorker,也就是说命中了缓存。内存缓存是内存中的缓存(相对于磁盘缓存是硬盘上的缓存)。按照操作系统的常识:先读内存,再读硬盘。WeChat_20220119110918.png截图磁盘缓存也叫HTTP缓存。顾名思义,就是一个存储在硬盘上的缓存,所以它是持久化存储的,实际存??在于文件系统中。它允许跨会话甚至跨站点使用相同的资源,例如,如果两个站点使用相同的图像。WeChat_20220119110855.png截图以上缓存策略和缓存/读取/失效动作都是浏览器内部判断的。我们只能设置响应头的某些字段来告诉浏览器,而不能自己操作。服务工作给了我们另一种更灵活、更直接的操作方式。我们可以从Chrome的应用中找到ServiceWorker。这个缓存是永久性的,也就是说,如果你关闭了TAB或者浏览器,下次打开它时它仍然存在(但内存缓存不是)。有两种情况会导致此缓存中的资源被清除:手动调用APIcache.delete(resource)或容量超过限制被浏览器完全清空。后记本文为作者个人学习笔记,如有错误,敬请指出,万分感谢!如果本文对您有帮助,请点个赞~~
