一、背景
浏览器都有一个缓存机制,简单点说就是同路径同名文件会默认被缓存下来,提升下次访问时的速度,默认只有刷新页面或长时间未访问时才会刷新缓存。
而spa单页面应用是通过路由切换来访问不同页面,路由切换时不会刷新页面,所有会存在缓存问题。
为了避免这个问题,一般都会配置文件名hash,hash一般采用content hash,文件内容有修改时就会生成新的文件名hash,防止项目修改发布后由于浏览器缓存导致页面未更新。
然而对于index.html模板文件,一般是不做hash处理的,在没有做特殊处理的情况下这个index.html文件会一直被浏览器缓存,由于所有的js/css等资源文件名的引入都是在html里,如果html模板文件未更新,就会导致项目修改发布了也未及时生效的问题,在pc端浏览器里可以通过手动刷新页面处理,而在移动端特别是hybrid混合应用里就束手无策了。
二、浏览器缓存机制
浏览器的缓存机制在网上能找到一堆文章,这里就简单总结一下,不做详细说明。 浏览器缓存分为强缓存和协商缓存,缓存配置只能通过服务端设置,前端无法控制。
1、强缓存
- 强缓存通过响应头中的 Cache-Control 或 Expires 字段来设置,
- 可设置为长期或指定时间或强制不缓存,
- 优先级高于协商缓存,
- 配置了强缓存的页面需要通过ctrl+f5来强制刷新页面。
2、协商缓存
- 协商缓存通过响应头中的 Etag 或 Last-Modified 字段来设置,
- 配置了协商缓存后下次访问时请求头会自动带上 If-None-Match 或 If-Modified-Since 字段,服务端通过请求头里的这个值和服务端访问文件的值作对比来判断服务端文件是否已更新,已更新返回200重新获取,未更新返回304从缓存读取。
- Etag是对比文件的hash值,Last-Modified 是对比文件的最后更新时间。
- 优先级低于强缓存
- 配置了协商缓存的页面通过f5或鼠标点击刷新按钮即可刷新页面。
三、解决html文件缓存
了解了浏览器的缓存机制后就能找到解决方案了,也就是配置协商缓存或强缓存两种基本方案,以nginx服务器为例。
1、协商缓存方案
Etag 和 Last-Modified 选择一种即可,都设置也行,推荐Etag,也就是在服务端开启etag。
http {
etag: on;
}
2、强缓存方案
Cache-Control 或 Expires 选择一种即可,推荐Cache-Control。
location / {
if ($request_filename ~* .*\.html$) {
add_header Cache-Control "no-cache, no-store";
}
}
location ^~ /h5 {
if ($request_filename ~* .*\.html$) {
add_header Cache-Control "no-cache, no-store";
}
}
location ^~ /h5 {
root html;
try_files $uri $uri/ /h5/index.html;
if ($request_filename ~* .*\.html$) {
add_header Cache-Control "no-cache, no-store";
}
}
四、验证方式
这里介绍一下方法验证是否生效:
- 首先浏览器f12打开开发者工具,切换到network栏,点击Doc筛选栏,
- 如图,Doc即document,可以筛选出主路由的html文件请求(上述home路由即index.html),只需查看该请求的status状态码和size即可判断。
- 304状态码就表示触发了协商缓存,200状态码且size显示为disk cache或memery cache即表示为触发了强缓存,200状态码且size显示为实际大小表示正常请求数据未触发缓存。
- 由于缓存是第二次访问才会触发,且刷新浏览器不走缓存,所以要加以验证可以这么做:先访问页面,然后改变浏览器的域名地址回车,让浏览器访问另一域名的网址,然后点击浏览器的后退按钮,这是再查看页面的status和size状态即可判断。
- 如果通过强缓存方案设置html强制不缓存,查看结果如下:
- 对于做app和小程序内嵌webview的h5开发来说,处理html缓存问题很有必要。
|