之前我的组长问了我一个有关缓存的问题,前端怎么做缓存。但是我之前缓存方面的知识了解不多,最近查了相关方面资料,有了比较深的认识,在这里做个总结。
Web缓存概念
Web缓存是指一个Web资源(如html页面,图片,js,数据等)存在于Web服务器和客户端(浏览器)之间的副本。缓存会根据进来的请求保存输出内容的副本;当下一个请求来到的时候,如果是相同的URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,还是向源服务器再次发送请求。
如何进行缓存
web页面中包括有很多资源,如JS,CSS,图片,页面的访问者进行网页浏览时,会进行很多HTTP请求来下载这些资源。当然第一次访问页面的时候,请求下载是不可避免的,缓存则是为了在后续的页面访问中避免重复的请求下载。设置缓存有以下几个方法,都是用后端通过服务器框架来设置:
-
Expires头:
web服务器用expires来告诉web客户端它可以使用一个资源的当前副本,直到限定时间为止
Expires: Sunday 26 October 2019 01:00 GMT
如果为页面中某个资源如JS文件返回了这个头,浏览器在后续的页面浏览中会使用缓存的JS文件
-
同时指定Expires和Cache-Control中的 max-age
Cache-Control:max-age=100000000
Expires有一些短板,要求服务器和客户端时钟严格同步,过期时间需要经常检查,当快过期时还要在服务器重新配置新的日期。但是max-age设置的时间没有固定到哪天,是限定资源被首次请求后的一段时间。而HTTP1.1及以上版本才支持Cache-Control,所以保险操作是仍设置Expires。
如何不使用缓存
这里说的不使用缓存是指将资源配置为浏览器代理缓存后,当我们更新了这些资源到服务器,用户如何再次请求新的资源。当设置了Expires头,直到过期之前浏览器不会检查任何更新,一直使用硬盘的缓存版本。
最有效的方法是修改链接,这样全新的请求将从原始服务器下载最新的内容
Etag——比较服务器文件和浏览器缓存文件的匹配
当缓存的资源过期了,或者用户刷新了页面。浏览器在使用这份缓存资源前先检测它是否有效,这被称为条件GET请求,执行有效性检查。如果浏览器缓存有效,原始服务器不会返还整个资源文件,而是“304 Not Modified”。
而服务器检测缓存组件与服务器组件的匹配依靠Etag和Last-Modified:
- Last-Modified:浏览器使用缓存文件的If-Modified-Since头将最新修改日期传到服务器做比较,如果匹配服务器资源的最新修改日期,那么返还304响应,而不是整个资源文件;
- Etag:一种实体标签,位置标志了一个资源文件的某个特定版本的字符串,由服务器来根据资源文件的特定信息生成添加。
但是Etag用于多台服务器的网站会影响到服务器性能和增加带宽开销,因为*相同的资源文件*,通过*不同服务器*进行请求,尽管在服务器上该资源文件一切属性位置都想同,但是不同的服务器仍然拥有不同的iNode和*Etag*。
Etag之外的前端缓存——给资源文件添加hash
设置Expires和max-age为最大时间的同时,同时设置Etag,前端生成各类资源文件的时候添加唯一的hash值构成文件名,这样只要放到服务器上的资源文件其带有hash值的文件名没有改变,浏览器永远使用缓存,并且不会发出任何请求,返回from disk cache或者from memory cache,这其中的区别如下:
200 from memory cache 不访问服务器,直接读缓存,从内存中读取缓存。此时的数据时缓存到内存中的,当kill进程后,数据将不存在
200 from disk cache 不访问服务器,直接读缓存,从磁盘中读取缓存,当kill进程时,数据还是存在。
304 Not Modified 访问服务器,发现数据没有更新,服务器返回此状态码。然后从缓存中读取数据。
前端缓存方案
- HTML文件不做缓存
- CSS和JavaScript,使用MD5,时间戳,版本号和长缓存方式