当前位置: 首页 > Web前端 > HTML

浏览器缓存机制及前端优化方案介绍

时间:2023-03-29 12:13:51 HTML

后台缓存对于性能优化是个好东西。但是如果缓存使用不好,就会出现一系列的问题:为什么我的页面显示的还是老版本?请刷新网页白屏...以上问题你或多或少都遇到过。归根结底是使用缓存的姿势不对。今天,我们就一起来了解一下浏览器是如何缓存的,想要什么?如何科学使用缓存浏览器缓存机制1、什么是浏览器缓存?简单的说,浏览器将http请求的资源保存到本地,以备下次使用,也就是浏览器在这里缓存了一个点:http响应头决定了浏览器对资源采用什么样的缓存策略2.浏览器是否读取缓存或请求数据?用户第一次请求资源的全过程3、缓存过程的分类——强缓存/协商缓存根据是否请求服务,我们将缓存过程分为强缓存和协商缓存,也可以理解为必然的过程称为强缓存,如果没有强缓存,则与服务器协商强缓存。强缓存看响应头中的Expires和Cache-Control字段。Expires是一个老规范,代表一个绝对有效的时间。在此之前,缓存会被命中。如果超过了,缓存就会失效,而且因为是和本地时间(可以随意修改)进行比较,所以会造成缓存混乱。Cache-Control是一种新规范,其优先级高于Expires。也是目前主要使用的缓存策略。max-age字段表示一个相对时间。例如Cache-Control:max-age=3600表示该资源有效期为3600秒。其他配置no-cache:需要协商缓存,向服务器发送请求确认是否使用缓存。no-store:禁止使用缓存,每次都要重新请求数据。public:可以被所有用户缓存,包括终端用户和CDN等中间代理服务器。private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器缓存。协商缓存当强缓存没有命中时,浏览器会向服务器发送请求,服务器会根据header中的部分信息判断是否命中缓存。如果命中则返回304,告诉浏览器资源没有更新,可以使用本地缓存。协商缓存查看标头中的Last-Modified/If-Modified-Since和Etag/If-None-Match。缓存生效,返回304,缓存无效,返回200且请求结果Etag优先级Last-Modified高于Last-Modified/If-Modified-Since浏览器第一次请求资源时,Last-Modify将被添加到服务器返回的标头中。Last-modify是表示资源最后修改时间的时间。当浏览器再次请求该资源时,请求头中会包含If-Modify-Since,也就是缓存之前返回的Last-Modify。服务端收到If-Modify-Since后,根据资源的最后修改时间判断是否命中缓存,命中则返回304使用本缓存,否则返回200并请求最新的资源。Etag/If-None-Matchetag是更严格的检查。一般情况下,时间检查就够了,但是我们想象一个场景,如果我们在短时间内修改了服务器资源,然后很快又改回来,理论上这种情况下,本地缓存还是可以使用的。这就是etag诞生的场景。使用etag时,服务端对资源进行类哈希运算,得到一个标识符(内容不变,标识符不变),返回给客户端。再次请求时,客户端会将If-None-Match中etag的值带入服务端进行比对校验。如果命中则返回304使用缓存,否则重新请求资源。注意:由于e-atg服务器计算的额外开销,性能较差。扩展:DNS缓存和CDN缓存DNS缓存。互联网上的所有通信行为都需要IP连接。DNS解析是指通过域名地址获取对应IP的过程。基本上有DNS的地方就有缓存,查询顺序如下:一般我们日常接触到的是有时候内网域名访问需要修改本地主机映射关系,或者某些情况下科学上网,修改本地主机URL即可正常访问CDN缓存CDN缓存从两个层面优化资源访问:降低根服务的分发压力,缩短物理传输距离(跨地域访问)。CDN节点解决了跨运营商、跨地域访问的问题,访问时延大大降低。大多数请求在CDN的边缘节点完成,CDN起到分流的作用,减轻源服务器的负载。CDN服务一般由运营商提供。我们只需要知道如何验证CDN是否生效就可以查看域名是否配置了CDN缓存。ping{{域名}}会看到被重定向到另一个地址(alikunlun),例如:pingcustomer.kukahome。com来检查我们的页面资源是否命中CDN缓存,通过检查对应的header是否有X-cache:HIT字段,然后才命中CDN缓存。注意这里的名字不是固定的,但是一般都会有一个HIT的标志。如果是MISS或None,则没有缓存命中。前端针对缓存部署优化方案构建演进。优化的核心思想是如何更好更快地加载资源,以及如何保证资源的新鲜度。这个优化过程也分为几个阶段,其中一些阶段已经不再适用于当前场景,不过大家也可以了解一下早期的图标合并精灵(sprite),多脚本文件合为一个文件:目的是为了提速通过减少碎片请求数来提升资源加载(相关知识点是浏览器一般最多只支持6个并发请求,同时请求数需要控制在合理范围内)现在精灵map已经基本被iconfont取代,js加载更多的是分模块异步加载,而不是盲目合并随着web应用的推广和浏览器缓存技术的普及,前端缓存问题也随之而来。最常见的问题是服务器端资源发生变化,但客户端资源无法更新。在这个阶段,工程师们想到了很多解决方案。在静态资源路径中加上“?v=version”或者使用时间戳来命名资源文件,有点像打包时修改了缓存。由于时间戳无法识别文件内容是否发生变化,所以才有了后来的hashscheme。理论上,只要哈希后的文件内容不变,文件名就保持不变,大大提高了缓存的使用寿命,也是现代常用打包工具的默认配置。然后,重点是我们已经对html文件中链接的资源做了上面的操作。一系列的优化,但是html本身也是一个静态资源,客户访问页面的时候不会带上所谓的时间戳或者版本号,导致很多时候服务器资源虽然更新了,但是客户端还是用旧的html文本发起请求,此时会导致各种问题,包括但不限于白屏、显示旧版本页面等。为了解决这个问题,目前主流的解决方案是不缓存html(一般单页应用的html文件小,大的是js),本地只缓存js、css等静态文件。那么,如何防止浏览器缓存html,目前是通过设置Cache-Control来实现的,有前端解决方案和后端解决方案,风险提示,前端解决方案很不靠谱,很多默认配置的后端会覆盖前端的解决方案,你可以理解,请在生产中使用后端配置。通过html标签设置缓存控制//旧协议//旧协议//目前主流的部署配置目前主流的前端部署方式都是使用nginx,我们看看nginx是如何禁用html缓存的location/{root**;#配置页面不缓存以html和htm结尾的文件,代理重新验证";}indexindex.htmlindex.htm;}private会影响CDN缓存命中率,但是CDN缓存本身也会有版本问题,No-cache在量不大的时候也可以禁止。使用缓存,但在使用前必须在服务器端验证。它可以是no-cache或max-age=0。no-store完全禁用缓存。Must-revalidate和no-cache类似,强制在服务端进行验证。作用于一些特殊的场景,比如发送验证请求,但是发送失败等。proxy-revalidate和上面类似,需要代理缓存服务验证有效性上面的配置可以根据需要灵活配置项目的,考虑到浏览器对缓存协议有一定的支持,不同的是,如果你只是想简单粗暴的禁用html缓存也无所谓,不会有特别大的影响,除非你需要特殊场景注意调优。这都是关于资源压缩的。另一种前端构建优化常用的方法是Gzip资源压缩,可以大大减少资源包的大小。一般的前端构建工具都有插件支持。需要注意的是,配置生效也需要nginx。http{gzip_static开启;gzip_proxiedany;}如果生效,可以在响应头中看到content-encoding:gzip