不同服务器在不同浏览器上的缓存行为
- Nginx服务器
- Chrome浏览器
- Firefox浏览器
- IE浏览器
- Tomcat服务器
- 最佳实践(应该怎么设置缓存)
下面我们分析不同服务器在不同浏览器上的缓存行为,默认的项目目录如下:
index.html 和 test.html 文件内容基本一样,只是为了测试浏览器会不会对文件名采取不同缓存行为。
文件内容如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>index.html缓存测试</title> <link rel="stylesheet" href="./index.css"> <link rel="stylesheet" href="./wentest.css"> </head> <body> <h1>index.html缓存测试</h1> <img src="./imgtest.png" alt=""> <img src="./index.jpg" alt=""> <img src="./test02.jpg" alt=""> <script src="./index.js"></script> <script src="./wentest.js"></script> </body> </html>
1、Nginx服务器默认配置
(以下用的 Nginx 版本都是 1.12.2)
我们以默认的 Nginx 配置为准。下面的 Nginx 配置跟默认配置基本保持一致,只是修改了访问时指向的资源路径,未做任何缓存配置。
Nginx 配置如下:
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
location =/ {
root /usr/local/nginx/html/mytest;
index index.html;
}
location ~* \.(html|gif|jpg|jpeg|css|js|png|ico|eot|ttf|woff|svg)$ {
root /usr/local/nginx/html/mytest;
}
}
}
分别访问 index.html 和 test.html,可以发现,两者的缓存行为是一样的,可以证明,浏览器的缓存行为跟文件名无关。
1.1、Chrome浏览器缓存行为
以下用的Chrome浏览器版本都是 97.0.4692.99(正式版本) (64 位)
1.1.1、首次访问
第一次访问结果如下,可以看到第一次访问状态码都是 200,且都是没有缓存记录的,
html 文件和 其他文件的请求头和响应头分别如下:
- html 文件:
- JS、CSS和图片文件:
1.1.2、多次访问
在进行首次访问后,多次刷新(F5键刷新),可以看到,此时浏览器对资源进行了缓存。
可以发现,html 文件的缓存行为和其他资源的不一样。
间隔比较长时间再刷新,可以看到,图片资源缓存变成了协商缓存,其他保持原样。如下:
html 文件和 其他文件的请求头和响应头分别如下(未间隔较长时间):
- html 文件:
- JS、CSS 和 图片文件:
1.1.3、结论
Nginx 默认配置,在 Chrome 浏览器中
- 首次访问,永远不会使用缓存(因为浏览器此时还没有缓存该资源),即会给资源的响应头加上协商缓存( 包括ETag 和 Last-Modified )的标识,并且在请求头中会带上强制缓存标识 Cache-Control: no-cache(实际上也是告诉服务器使用协商缓存)。
- 多次访问,此时全部使用缓存,不同的是,html 文件会使用协商缓存,而其他资源都使用强缓存。而如果间隔较长时间再访问的话,html 和图片资源都使用协商缓存,而其他资源都使用强缓存。
所以说,Nginx 默认配置,在 Chrome 浏览器中,首次访问,资源不会使用缓存;多次访问时,html 文件会使用协商缓存,而其他资源都使用强缓存;而如果间隔较长时间再访问的话,html 和图片资源都使用协商缓存,而其他资源都使用强缓存。
1、默认Nginx配置的缓存
一般来说,通过 nginx 静态资源服务器,会默认给资源带上强缓存、协商缓存的 header 字段。
下面的 Nginx 配置基本跟默认配置一样,只是修改访问时指向的资源路径,我们使用下面的 Nginx 配置来配置 Nginx 静态服务器:
#user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; server { listen 80; server_name localhost; location =/ { root /usr/myTestData/web01; index index.html; } location ~* \.(html|gif|jpg|jpeg|css|js|png|ico|eot|ttf|woff|svg)$ { root /usr/myTestData/web01; } } }
我们给 web01 项目添加了首页 index.html、一个 css 文件和一张图片。第一次请求时,肯定都是报 200,因为还未请求过该资源,都是需要从服务器获取,如下:
当我们再次请求时,通过 F5 刷新,可以看到在不同浏览器中有不同的表现:
- 在 Chrome 浏览器中:
index.html 文件:
index.css 文件:
图片:
- 在Firefox浏览器中:
index.html 文件:
- 在IE浏览器中:
可以看到,Chrome 和 Firefox、IE 不同浏览器的表现不太一样,但默认都有协商缓存在里面。
1.1、更新服务器资源(模拟生产部署)
我们全量更新服务器上的 html、css、图片文件,模拟生产上的全量部署。
部署完成后,通过在浏览器 F5 来进行更新。第一次请求如下:
index.html 文件:
可以看到,last-modified 已经发生了改变,同时你可以在页面上看到所有的资源都得到了更新。
第二次请求就得到了缓存:
上面是用 Firefox 浏览器演示的情况,如果是用 Chrome 浏览器可能会有点问题。在 Chrome 浏览器中,html 和 css 文件通过协商缓存能得到更新,但是图片资源不会得到更新,需要 ctrl+F5 进行强制更新才行。
一般项目在配置时,会配置不缓存 html 文件。原因:html文件最容易碰到缓存问题,重新发版后,一旦客户端继续使用原来的缓存,那么在原来的缓存过期之前,没有任何办法去触使客户端更新,除非一个个通知android客户手动清除app缓存数据,通知IOS用户卸载重装。所以配置html缓存策略时要格外小心,一般可以不缓存 html 文件。
其他静态资源(css、js、img)则配置缓存。原因:此类资源改动较少,为了提升用户体验,一般都需要配置缓存,但反而不容易碰到缓存问题。因为现在的前程工程也都需要build,在build时工具会自动在文件名上加时间戳,这样一发新版时,只要客户端请求了新版的html,里面引用的js/css/jpg等都已经换了路径,肯定也就不会使用本地的缓存了。