浏览器缓存及应用

373 阅读4分钟

一 浏览器缓存 分为强缓存对比缓存

强缓存 expire cache-control

对比缓存 etag last-modified if-modified-since

本质上都是浏览器对header信息的处理,发送http请求时,http 返回的header携带返回的。

** 1 如果你用express或者java开发,你可以在代码里设置http头信息,如下**

强缓存使用场景,oss的图片资源,一旦发布之后几乎不会修改,所以oss图片服务器可以配置30分钟的缓存, 配置完之后,刷新页面之后,图片并不会向服务器发送请求,而是直接返回200(memery cache)

协商缓存http状态码304,会发生一次Http请求,但服务端端返回了(空的报文头),从而减小了网络开销.

response.setHeader("Cache-Control", "public");

** 2 如果你是前端开发,那么如果用nginx部署前端项目的话,可以在nginx配置 ,如下**

location   /  {
		   add_header Cache-Control no-cache; 

那么,我们为什么要在项目里用缓存?如何在项目里用缓存?

部署前端项目,将项目打包完成之后 html、css、js 文件,部署到nginx服务器, 好了,浏览器访问,正常返回200

image.png

然而,这就完了?每次浏览器访问时,都从服务器拉取资源,这样不是很浪费宽带,而且对于网络传输,用户每次都需要获取服务器文件,加载速度岂不是很慢。

这时候,缓存就要上场了,nginx增加配置,强制浏览器使用本地缓存(cache-control/expires),不要和服务器通信,这样用户只需要从服务器获取一次资源,之后就不会和服务器交互了,但是,如果服务器css、js需要更新呢?用户不知道服务器改了啊?

很好,相信有人想到了办法:通过更新页面中引用的资源路径,让浏览器主动放弃缓存,加载新资源。好像这样:

<link rel="styles" href='./home.css?v=1.0.0'>
<link rel="styles" href='./main.css?v=1.0.0'>

那么问题又来了,每次都要把版本号(v=1.0.0)改掉,那么如果只是home.css文件改了,但是main.css文件没改呢?

什么东西与文件内容相关呢?我们会很自然的联想到利用 [数据摘要要算法]对文件求摘要信息,摘要信息与文件内容一一对应,就有了一种可以精确到单个文件粒度的缓存控制依据了。好了,我们把url改成带摘要信息的:

image.png

这样似乎解决了,该缓存的缓存,该更新的更新。

但是,上线过程中,如何保证用户正常使用呢??

  • 先部署页面,再部署资源:在二者部署的时间间隔内,如果有用户访问页面,就会在新的页面结构中加载旧的资源,并且把这个旧版本的资源当做新版本缓存起来,其结果就是:用户访问到了一个样式错乱的页面,除非手动刷新,否则在资源缓存过期之前,页面会一直执行错误。\

  • 先部署资源,再部署页面:在部署时间间隔之内,有旧版本资源本地缓存的用户访问网站,由于请求的页面是旧版本的,资源引用没有改变,浏览器将直接使用本地缓存,这种情况下页面展现正常;但没有本地缓存或者缓存过期的用户访问网站,就会出现旧版本页面加载新版本资源的情况,导致页面执行错误,但当页面完成部署,这部分用户再次访问页面又会恢复正常了。

看上图,用文件的摘要信息来对资源文件进行重命名,把摘要信息放到资源文件发布路径中,这样,内容有修改的资源就变成了一个新的文件发布到线上,不会覆盖已有的资源文件。上线过程中,先全量部署静态资源,再灰度部署页面,整个问题就比较完美的解决了。

所以,大公司的静态资源优化方案,基本上要实现这么几个东西:

image.png

  1. 配置超长时间的本地缓存 —— 节省带宽,提高性能\

  2. 采用内容摘要作为缓存更新依据 —— 精确的缓存控制\

  3. 静态资源CDN部署 —— 优化网络请求\

  4. 更资源发布路径实现非覆盖式发布 —— 平滑升级

参考地址www.zhihu.com/question/20…