nginx-自动获取最新静态文件

需求:

前端每次发版完,有部分前端文件是更新了的,但是客户访问却拿不到最新的前端文件,总不能让每个客户都手动清除浏览器缓存。

要实现让浏览器自己去获取最新的前端文件。

原理:

Nginx给请求的响应头中添加不缓存的策略。

# 设置缓存策略为不缓存:Http 1.1

add_header Cache-Control no-cache;

# 设置缓存策略为不缓存:Http 1.0

add_header Pragma no-cache;

# 设置缓存启用和缓存时间:Http 1.0

add_header Expires 0;  # 缓存时间为0,即立即过期

为了向下兼容,可以将Http 1.0的配置也写上:

add_header Pragma no-cache;

add_header Expires 0;

优先级从高到低

Pragma -> Cache-Control -> Expires

同时出现Pragma和Cache-Control时,以Pragma为准。

同时出现Cache-Control和Expires时,以Cache-Control为准。

按文件类型进行缓存:

而前端文件常见的有:html、js、css等。

针对不同的文件类型,可以有不同的缓存策略。

如果你的前端每次发版js和css文件名都会携带hash码,即每次发版后的文件名都不一样,客户端自然能拿到最新。

那么只需要针对html文件设置不缓存的请求头策略。

写法一:

# 前端静态文件

location ~* \.(gif|jpg|jpeg|png|css|js|ico|eot|otf|fon|font|ttf|ttc|woff|woff2)$ {

    root /var/www/zhian_cloud/;

}

# 前端html文件

location / {

    #  对html文件禁用缓存,任何时候都不缓存,拿到最新的

    add_header Cache-Control 'no-cache, must-revalidate, proxy-revalidate, max-age=0';

    root /var/www/zhian_cloud/;

    index index.html index.htm;

    try_files $uri /index.html;

}

写法二:直接匹配html文件,单独添加响应头

    location / {

        index index.html;

        root /var/www/zhian_cloud/;

    

        if ($request_filename ~* .*\.(?:htm|html)$) {

            add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";

        }

        try_files $$uri /index.html;

    }

Cache-Control

Cache-Control也是一个通用首部字段,这意味着它能分别在请求头和响应头中使用。

作为请求头时,可选值有:

no-cache:

告知(代理)服务器不直接使用缓存,要求向源站服务器发起请求。

no-store:

所有内容都不会被保存到缓存或Internet临时文件中。

max-age=delta-seconds:

告知服务器客户端希望接收一个存在时间(age)不大于delta-seconds秒的资源。

max-stale[=delta-seconds]:

告知(代理)服务器客户端愿意接收一个超过缓存时间的资源,若有定义delta-seconds则为delta-srconds秒,若没有则为任意超出的时间。

min-freash=delta-seconds:

告知(代理)服务器客户端希望接收一个在小于delta-seconds秒内被更新过的资源。

no-transform:

告知(代理)服务器客户端希望获取实体数据没有被转换(比如压缩)过的资源。

only-if-cached:

告知(代理)服务器客户端希望获取缓存的内容(若有),而不用向源站服务器发去请求。

cache-extension:

自定义扩展值,若服务器不识别该值将被忽略。

作为响应头时,可选值有:

public:

表名任何情况下都得缓存该资源(即使是需要http认证的资源)。

Private[="field-name"]:

表明返回报文中全部或部分(若指定了field-name则为field-name的字段数据)仅开放给某些用户(服务器指定的share-user,如代理服务器)做缓存使用,其他用户则不能缓存这些数据。

no-cache:

不直接使用缓存,要求向服务器发起(新鲜度校验)请求。

no-store:

所有内容都不会被保存到缓存或Internet临时文件中。

max-age=delta-seconds:

告知客户端该资源在delta-seconds秒内是新鲜的,无需向服务器发请求。

s-maxage=delta-seconds:

同max-age,但仅应用于共享缓存(如代理)。

no-transform:

告知客户端缓存文件时不得对实体数据做任何改变。

only-if-cached:

告知(代理)服务器客户端希望获取缓存的内容(若有),而不用向源站服务器发去请求。

must-revalidate:

当前资源一定是向源站服务器发去验证请求的,若请求失败会返回504(而非代理服务器上的缓存)。

proxy-revalidate:

与must-revalidate类似,但仅能应用于共享缓存(如代理)。

cache-extension:

自定义扩展值,若服务器不识别该值将被忽略。

public和private的选择

如果你用了CDN,你需要关注下这个值。CDN厂商一般会要求cache-control的值为public,提升缓存命中率。

如果你的缓存命中率很低,而访问量很大的话,可以看下是不是设置了private,no-cache这类的值。

如果定义了max-age,可以不用再定义public,它们的意义是一样的。

缓存校验

在缓存中,我们需要一个机制来验证缓存是否有效。比如服务器的资源更新了,客户端需要及时刷新缓存;又或者客户端的资源过了有效期,但服务器上的资源还是旧的,此时并不需要重新发送。缓存校验就是用来解决这些问题的,在http 1.1 中,我们主要关注下Last-Modified 和 etag 这两个字段。

1、Last-Modified

服务端在返回资源时,会将该资源的最后更改时间通过Last-Modified字段返回给客户端。客户端下次请求时通过If-Modified-Since或者If-Unmodified-Since带上Last-Modified,服务端检查该时间是否与服务器的最后修改时间一致:如果一致,则返回304状态码,不返回资源;如果不一致则返回200和修改后的资源,并带上新的时间。

If-Modified-Since和If-Unmodified-Since的区别:

If-Modified-Since:告诉服务器如果时间一致,返回状态码304。

If-Unmodified-Since:告诉服务器如果时间不一致,返回状态码412。

2、etag

单纯的以修改时间来判断还是有缺陷,比如文件的最后修改时间变了,但内容没变。对于这样的情况,我们可以使用etag来处理。

etag的方式是这样:服务器通过某个算法对资源进行计算,取得一串值(类似于文件的md5值),之后将该值通过etag返回给客户端,客户端下次请求时通过If-None-Match或If-Match带上该值,服务器对该值进行对比校验:如果一致则不要返回资源。

If-None-Match和If-Match的区别:

If-None-Match:告诉服务器如果一致,返回状态码304,不一致则返回资源。

If-Match:告诉服务器如果不一致,返回状态码412。

Http状态码304:

当客户端(通常是浏览器)向web服务器发送一个请求,如果web服务器返回304响应,他不包含任何响应的内容,只是提示客户端缓存的内容是最新的,可以直接在客户端的缓存中获取。这种方法可以节省带宽,避免重复响应。

用户刷新访问行为

1、在URL输入栏中输入然后回车/通过书签访问

可以看到返回响应码是 200 OK (from cache),浏览器发现该资源已经缓存了而且没有过期(通过Expires头部或者Cache-Control头部),没有跟服务器确认,而是直接使用了浏览器缓存的内容。其中响应内容和之前的响应内容一模一样,例如其中的Date时间是上一次响应的时间。

2、F5/点击工具栏中的刷新按钮/右键菜单重新加载

F5的作用和直接在URI输入栏中输入然后回车是不一样的,F5会让浏览器无论如何都发一个HTTP Request给Server,即使先前的响应中有Expires头部。

其中Cache-Control是Chrome强制加上的,而If-Modified-Since是因为获取该资源的时候包含了Last-Modified头部,浏览器会使用If-Modified-Since头部信息重新发送该时间以确认资源是否需要重新发送。 实际上Server没有修改这个index.css文件,所以返回了一个304(Not Modified),这样的响应信息很小,所消耗的route-trip不多,网页很快就刷新了。

3、Ctl+F5

Ctrl+F5是彻底的从Server拿一份新的资源过来,所以不光要发送HTTP request给Server,而且这个请求里面连If-Modified-Since/If-None-Match都没有,这样Server不能返回304,而是把整个资源原原本本地返回一份,这样,Ctrl+F5引发的传输时间变长了,自然网页Refresh的也慢一些。我们可以看到该操作返回了200,并刷新了相关的缓存控制时间。

实际上,为了保证拿到的是从Server上最新的,Ctrl+F5不只是去掉了If-Modified-Since/If-None-Match,还需要添加一些HTTP Headers。

例如请求头中会添加以下两个字段:

Cache-Control: no-cache Pragma: no-cache

按照HTTP/1.1协议,Cache不光只是存在Browser终端,从Browser到Server之间的中间节点(比如Proxy)也可能扮演Cache的作用,为了防止获得的只是这些中间节点的Cache,需要告诉他们,别用自己的Cache敷衍我,往Upstream的节点要一个最新的copy吧。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值