vlambda博客
学习文章列表

【前端开发日常 - 5】七牛CDN上的网页缓存问题及HTML禁止缓存

需求背景

前端开发的页面打包之后,为了提高访问的速度,往往会采用CDN(Content Delivery Network,内容分发网络)加速,通过将静态资源缓存到离用户很近的相同网络运营商的CDN节点上,不但能提升用户的访问速度,还能节省服务器的带宽消耗,降低负载。但是同样的,我们也不得不面临一些问题(以七牛CDN为例):

1、CDN缓存往往导致我们发布了新版网页,用户访问到的总是旧的页面;

2、大量刷新文件成本较高,且文件和目录的刷新有次数限制;

3、浏览器的本地缓存部分文件难以清除。


解决方案

阶段一 刷新关键文件缓存

在前端开发中,通过打包得到的静态资源往往不会经常变动,通常只有个别js文件和html文件改变,在发布新版本之后,可以登录七牛CDN,通过【CDN】-【刷新预取】填入需要刷新的文件进行刷新。


阶段二 为文件访问地址加上hash或时间戳

如果使用webpack打包,我们可以通过webpack配置hash或自定义版本,为每次打包生成不同的文件名和访问路径,从而减少发布到CDN之后需要刷新的文件数量。


阶段三 使用新的路径发布网页

1、发布网页到携带版本号的前缀下,如path/1.0.0/,下一次发布的时候则改为path/1.0.1/;


阶段四 去除文件缓存(进行中)

第三阶段的发布依旧会存在问题:

2、部分APP的webview缓存非常顽固(比如钉钉版的网页版),会将我们的整个网页缓存到本地,导致不能访问新版网页。

阶段四是目前准备做的一种方式,目标是去除部分HTML被用户的浏览器缓存。

去除HTML缓存

首先,我们需要去除HTML的缓存,我们可以采取通过meta标签去除缓存:

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />

其中,Cache-Control 对 HTTP 1.1 使用,Pragma 对 HTTP 1.0 使用,Expires 对 proxies 使用。


修改CDD响应头的缓存设置

首先在七牛【CDN】 - 【域名管理】找到需要修改的域名,点击配置,再找到 【缓存配置】 - 【修改配置】,在里面配置不需要缓存的文件和目录。保存之后也记得去对需要清除缓存的文件进行刷新预取。

方案四还是在进行中,主要问题是七牛通过设置域名缓存之后,访问到的HTML文件依旧有一个很大的max-age,这将使得浏览器会长时间缓存文件,目前还在想办法处理中……

当然,通过设置整个 bucket 的配置参数是可以实现的,修改里面的 maxAge 选项,不过这将会对所有文件生效,并不可取。


核心代码

上面的各个阶段仅作为处理思路,下面来关注一下其它语言清除文件缓存的方式。

.htaccess (Apache)

<IfModule mod_headers.c>
  Header set Cache-Control "no-cache, no-store, must-revalidate"
  Header set Pragma "no-cache"
  Header set Expires 0
</IfModule>

Java Servlet

response.setHeader("Cache-Control", "no-cacheno-store, must-revalidate");
response.setHeader("
Pragma", "no-cache");
response.setDateHeader("
Expires", 0);

PHP

header('Cache-Control: no-cacheno-store, must-revalidate');
header('
Pragmano-cache');
header('
Expires: 0');

ASP

Response.addHeader "Cache-Control", "no-cacheno-store, must-revalidate"
Response.addHeader "
Pragma", "no-cache"
Response.addHeader "
Expires", "0"

ASP.NET

Response.AppendHeader("Cache-Control", "no-cacheno-store, must-revalidate");
Response.AppendHeader("
Pragma", "no-cache");
Response.AppendHeader("
Expires", "0");

Ruby on Rails

response.headers['Cache-Control'] = 'no-cacheno-store, must-revalidate'
response.headers['
Pragma'] = 'no-cache'
response.headers['
Expires'] = '0'

Python on Flask

resp.headers["Cache-Control"] = "no-cacheno-store, must-revalidate"
resp.headers["
Pragma"] = "no-cache"
resp.headers["
Expires"] = "0"

Google Go

responseWriter.Header().Set("Cache-Control""no-cache, no-store, must-revalidate")
responseWriter.Header().Set("Pragma""no-cache")
responseWriter.Header().Set("Expires""0")

参考文档

Disable browser caching with meta HTML tags:  http://cristian.sulea.net/blog/disable-browser-caching-with-meta-html-tags/