前几天按照Node.js中文社区上的教程,用Node.js搭了一个简单的静态文件服务器,其中有一个功能是提供缓存支持,在实践这一部分的过程中,我重新学习了缓存的相关知识,在这里作简单的梳理。
关于缓存的相关介绍,网上有不少文章,这里推荐三篇我认为不错的文章:
- http://blog.csdn.net/eroswang/article/details/8302191
- http://www.oschina.net/news/41397/web-cache-knowledge
- http://cloudbbs.org/forum.php?mod=viewthread&tid=15790
缓存是什么,简单的说,就是访问页面时不需要重新请求浏览器已经缓存的资源(如图片、css、js等),前提是这些位于服务器的资源并没有发生变更。所以,如何确定这些资源没有发生变更、如何控制缓存过期的时间成了必须解决的问题。这些内容在以上三篇文章中都有详细的介绍,我这里仅从四种使用情景来分析浏览器和服务器的交互过程。
情景一:用户第一次在浏览器中输入网址,或者通过链接访问某个网站
浏览器(客户端)发出请求,请求网页上的所有资源,一个资源对应一个请求,服务器端收到请求后,向客户端发送200的状态码,表示该资源请求成功,并返回响应头(response header)和数据体。其中,响应头包含了以下几个重要的头信息:
- last-modified:该资源(文件)的最后修改时间,为UTC格式
- Expires:该资源的缓存过期时间,为绝对时间,即过了这个指定时间后缓存失效,为UTC格式
- Cache-Control:通常通过max-age指定缓存过期时间,为相对时间,表示某次请求成功后多少秒内缓存可用,单位为秒
Cache-Control的出现是因为服务器端的时间可能存在误差,其优先级高于Expires。浏览器接收到响应后,会记录这些信息,方便之后的缓存控制。
情景二:用户第N次(N大于1)在浏览器中输入网址,或者通过链接访问某个网站
浏览器首先检查待请求的资源的状态,先检查Cache-Control,没有则检查Expires,如果缓存未过期,则浏览器不向服务器端发送请求,直接返回200 from cache,表明是从缓存中获取的资源。也就是说,就算服务器端该资源已经发生变化,只要缓存未过期,就不会重新请求资源,所以刷新的作用就体现出来了。
情景三:资源已经缓存,用户刷新页面(按F5)
浏览器向服务器发送资源请求,请求头中包含以下两个头信息:
- Cache-Control:其中max-age=0(刷新时置为0),表示本地缓存已过期,要向服务器确认
- if-modified-since:这是时间等于上一次成功请求该资源后从last-modified获取的时间,为UTC格式
服务器接收到请求,将待请求资源的最后一次修改时间和if-modified-since进行对比。如果前者与后者不相等,则说明文件已经变动,则重新下载该资源,并返回200状态码;如果前者与后者相等,则从本地缓存中获取,并返回304 Not Modified。
情景四:资源已经缓存,用户强制刷新页面(按Ctrl + F5)
强制刷新时,请求头中的Cache-Control的值设为no-cache,表示强制发送请求,此外请求头中无If-Modified-Since头信息,这样,无论缓存是否过期,无论服务器端文件是否发生变更,都会强制下载请求的资源,这就是所谓的“强制刷新”。
最后,附上用node.js实现静态文件服务器的教程:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。