掘金上有很多讲缓存讲得很精彩很透彻的文章,我这篇文章重在个人的学习吧,希望尽量能往老瓶里面装点新酒。好吧,废话不多说,马上进入主题。
众所周知,缓存分为两种。一种是强缓存,另外一种是协商缓存。如果命中强缓存,那么浏览器将不需要请求服务器直接拿缓存资源来使用。而协商缓存不管是否命中都要和服务器端发生交互的。因此在实际开发中,是希望更多的命中强缓存的,因为这样可以减少对服务器的请求,性能无疑会更好。
缓存匹配流程图:
强缓存
由上面的图可以看出来,强缓存的优先级是要比协商缓存高的。而控制强缓存的有两个http头字段控制。
- Expires
它是一个HTTP 1.0版本的一个HTTP头字段,用于声明缓存的过期时间。但是由于它记录的是一个绝对的时间,这就很可能会因为时区或者时间格式等问题导致缓存失效。因此现在在实际开发中基本已经很少使用了。
- Cache-Control
Cache-Control是一个HTTP 1.1版本的HTTP头字段。它的优先级会比Expires高,当二者同时存在时,浏览器会以Cache-Control作为缓存是否过期的依据。
值得注意的是no-cache并不是说不缓存,而是指每次请求都必须先请求一下服务器,其实跟协商缓存很类似。而真正的不缓存是no-store.另外一个常用的字段就是max-age.max-age表示缓存的内容在XXX秒内有效,这就可以很好的解决了Expires由于地区和格式引起的问题。
协商缓存
协商缓存等于每次浏览器请求资源之前都会先发一个请求给服务器查看资源是否有更改,如果资源没有更改即使资源过期了,浏览器照样可以拿缓存的内容来使用。可以说是一种更安全的缓存方案。
- Last-modified/If-Modified-Since
Last-modified表示资源最后修改的时间,响应头会带上这个标识。当浏览器浏览器请求完这个资源之后就会把这个时间记录下来。再次请求时,请求头会带上If-Modified-Since 的字段,服务器端收到后,就会根据If-Modified-Since的时间与资源最后的更改时间进行比较,看资源是否发生了更改。如果没有发生更改,则会返回状态码为304的响应,如果发生了更改就会返回状态码为200的响应。
- Etag/If-None-Match
Etag是由服务器端生成的一段hash code.默认的计算方式是“文件的最后修改时间16进制-文件长度16进制”。服务器端在响应客户请求的时候会带上Etag,之后客户端请求就会通过If-None-Match携带上Etag。然后客户端会根据是否命中来决定返回304还是200.
项目实践
上面说了这么多概念性的东西,下面我来说一下我自己项目中一些缓存的实践吧。我们在项目开发中关于缓存会有以下几点的设置:
-
1.将JS,CSS,图片等静态资源的有效时间设置得很大(max-age=31536000),尽量命中强缓存。
-
2.将html的资源的有效时间设置得很短(max-age=0,或者cahe-control:no-store/no-cache).这样可以避免html不更新读取不到最新得资源文件。
-
3.在使用webpack打包时,将js,css,图片等静态资源使用contentHash来命名打包出来的文件。
entry:{
main: path.join(__dirname,'./main.js'),
vendor: ['react', 'antd']
},
output:{
path:path.join(__dirname,'./dist'),
publicPath: '/dist/',
filname: 'bundle.[contentHash].js'
}
复制代码
- 4.最后部署时采用非覆盖式的部署。
最后
以上如果有说得不对的地方,欢迎指正~~