用node探究http缓存

用node搞web服务和直接用tomcat、Apache做服务器不太一样, 很多工作都需要自己做。缓存策略也要自己选择,虽然有像koa-static,express.static这些东西可以用来管理静态资源,但是为了开发或配置时更加得心应手,知其所以然,有了解http缓存的必要。另外,http缓存作为一个前端优化的一个要点,也应该有所了解。

什么是http缓存

RFC 7234 (https://tools.ietf.org/pdf/rfc7234.pdf)指出HTTP缓存是响应消息的本地存储,并且是控制其中消息的存储、检索和删除的子系统。

通俗讲: http协议规定了一些指令, 实现http协议的服务器和浏览器根据这些指令决定要不要以及如何把响应存储起来以备后续使用.

http缓存的意义

提高响应速度

减少带宽占用, 省流量

减小服务器压力

不指定任何与缓存有关的指令

这种情况下浏览器不做缓存, 每次都会想服务器请求. 但是比较奇怪的是在nginx的实现中, 这种情况下还是被代理服务器做了缓存.也就是说, 当多次请求同一个资源时, 代理服务器只向源服务器请求一次.

演示第1个例子nothing_1

强制缓存

所谓强制缓存就是给出资源的到期时间expires或者有效时间max-age, 在这个时间之内该资源应该被缓存.

如何让一个资源被强缓存

1.expires

这个字段定义了一个资源到期的时间. 看一个实际的例子:

用node探究http缓存

可以看到这个expires是个GMT时间, 它的工作机制是, 首次请求时, 服务器在响应中加上expires标识资源的到期时间, 浏览器缓存这个资源, 再次请求时, 浏览器将上一次请求到这个资源的过期时间与自己的系统时间对比, 若系统时间小于过期时间, 则证明资源没有过期, 直接用上次缓存的资源, 不必请求; 否则重新请求, 服务器在响应中给出新的过期时间.

演示第9个例子expires_9

const d = new Date(Date.now() + 5000); res.writeHead(200, { 'Content-Type': 'image/png', 'expires': d.toGMTString() }); res.end(img);

2.Cache-Control:[public | private,] max-age=\({n}, s-maxage=\){m}

expires 存在的问题是他依赖于客户端的系统时间, 客户端系统时间错误可能会引起判断错误. HTTP1.1增加了Cache-Control解决此问题, 这个指令值比较丰富, 常见的如下:

public/private: 标识资源能不能被代理服务器缓存, public 标识资源既能被代理服务器缓存也能被浏览器缓存, private标识资源只能被浏览器缓存, 不能被代理服务器缓存.

max-age: 用于指定在客户端缓存的有效时间, 单位s, 超过n秒需要重新请求, 不超过则可以使用缓存

s-maxage: 这个是针对代理服务器的, 表示资源在代理服务器缓存时间没有超过这个时间不必向源服务器请求, 否则需要.

no-cache: 有这个指令表示不走浏览器缓存了, 协商缓存还可以走

no-store: 强制无缓存, 协商缓存也不走了, 测试发下即使响应中有Last-Modified, 浏览器请求时页不会带If-Modified-Since

一个实例

用node探究http缓存

演示第2,3,4,5,7

协商缓存

所谓协商缓存就是客户端想用缓存资源时先向服务器询问, 如果服务器如果认为这个资源没有过期, 可以继续用则给出304响应, 客户端继续使用原来的资源; 否则给出200, 并在响应body加上资源, 客户端使新的资源.

1.Last-Modified与If-Modified-Since

这个机制是, 服务器在响应头中加上Last-Modified, 一般是一个资源的最后修改时间, 浏览器首次请求时获得这个时间, 下一次请求时将这个时间放在请求头的If-Modified-Since, 服务器收到这个If-Modified-Since时间n后查询资源的最后修改时间m与之对比, 若m>n, 给出200响应, 更新Last-Modified为新的值, body中为这个资源, 浏览器收到后使用新的资源; 否则给出304响应, body无数据, 浏览器使用上一次缓存的资源.

2.Etag与If-None-Match

Last-Modified模式存两个问题, 一是它是秒级别的比对, 所以当资源的变化小于一秒时浏览器可能使用错误的资源; 二是资源的最新修改时间变了可能内容并没有变, 但是还是会给出完整响应, 造成浪费. 基于此在HTTP1.1引入了Etag模式.

这个与上面的Last-Modified机制基本相同, 不过不再是比对最后修改时间而是比对资源的标识, 这个Etag一般是基于资源内容生成的标识. 由于Etag是基于内容生成的, 所以当且仅当内容变化才会给出完整响应, 无浪费和错误的问题.

演示第8, 10

如何选择缓存策略

https://developers.google.cn/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=zh-cn

附录

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpxgxf.html