好吧,我几乎要放弃了,但是如何禁用 Nginx 对 JavaScript 文件的缓存?我正在使用带有 Nginx 的 docker 容器。当我现在更改 JavaScript 文件中的某些内容时,我需要多次重新加载,直到新文件出现。
我怎么知道它是 Nginx 而不是浏览器/docker?
浏览器:我在命令行上使用
curl
模拟请求,遇到了同样的问题。此外,我正在使用 CacheKiller
插件并在 Chrome 开发工具中禁用了缓存。
Docker:当我连接到容器的bash,并在更改文件后使用
cat
,我立即得到正确的结果。
我将
nginx.conf
的 sites-enabled
更改为此(我在另一个 stackoverflow 线程中找到)
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|xml|html|htm)$ {
# clear all access_log directives for the current level
access_log off;
add_header Cache-Control no-cache;
# set the Expires header to 31 December 2037 23:59:59 GMT, and the Cache-Control max-age to 10 years
expires 1s;
}
然而,在重建容器后(并确保它在带有
cat
的容器中),它仍然没有工作。这是完整的.conf
server {
server_name app;
root /var/www/app/web;
# Redirect to blog
location ~* ^/blog {
proxy_set_header Accept-Encoding "";
sub_filter 'https://testproject.wordpress.com/' '/blog/';
sub_filter_once off;
rewrite ^/blog/(.*) /$1 break;
rewrite ^/blog / break;
proxy_pass https://testproject.wordpress.com;
}
# Serve index.html only for exact root URL
location / {
try_files $uri /app_dev.php$is_args$args;
}
location ~ ^/(app|app_dev|config)\.php(/|$) {
fastcgi_pass php-upstream;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
# Prevents URIs that include the front controller. This will 404:
# http://domain.tld/app_dev.php/some-path
# Remove the internal directive to allow URIs like this
internal;
}
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|xml|html|htm)$ {
# clear all access_log directives for the current level
access_log off;
add_header Cache-Control no-cache;
# set the Expires header to 31 December 2037 23:59:59 GMT, and the Cache-Control max-age to 10 years
expires 1s;
}
error_log /var/log/nginx/app_error.log;
access_log /var/log/nginx/app_access.log;
}
我有以下 nginx 虚拟主机(静态内容)用于本地开发工作以禁用所有浏览器缓存:
server {
listen 8080;
server_name localhost;
location / {
root /your/site/public;
index index.html;
# kill cache
add_header Last-Modified $date_gmt;
add_header Cache-Control 'no-store, no-cache';
if_modified_since off;
expires off;
etag off;
}
}
没有发送缓存头:
$ curl -I http://localhost:8080
HTTP/1.1 200 OK
Server: nginx/1.12.1
Date: Mon, 24 Jul 2017 16:19:30 GMT
Content-Type: text/html
Content-Length: 2076
Connection: keep-alive
Last-Modified: Monday, 24-Jul-2017 16:19:30 GMT
Cache-Control: no-store
Accept-Ranges: bytes
Last-Modified
始终是当前时间。
注意:nginx 的
$date_gmt
格式不符合 HTTP 规范(请参阅更改格式)。
要禁用特定文件扩展名的缓存(例如 OP 请求的 JS):
location ~* \.js$ {
expires -1;
}
请参阅下面 Nitai 的回答以扩展文件扩展名列表 - 使用非捕获组正则表达式模式。
expires
和 add_header
指令对 NGINX 缓存文件没有影响,那些纯粹是关于浏览器看到的内容。
你可能想要的是:
location stuffyoudontwanttocache {
# don't cache it
proxy_no_cache 1;
# even if cached, don't try to use it
proxy_cache_bypass 1;
}
虽然通常 .js 等是你要缓存的东西,所以也许你应该完全禁用缓存?
你正在寻找的是一个简单的指令,如:
location ~* \.(?:manifest|appcache|html?|xml|json)$ {
expires -1;
}
上面不会缓存()内的扩展。您可以为不同的文件类型配置不同的指令。
记住设置
sendfile off;
否则缓存标头不起作用。
我用这个剪断:
location / {
index index.php index.html index.htm;
try_files $uri $uri/ =404; #.s. el /index.html para html5Mode de angular
#.s. kill cache. use in dev
sendfile off;
add_header Last-Modified $date_gmt;
add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;
proxy_no_cache 1;
proxy_cache_bypass 1;
}
我有以下 Nginx 虚拟主机(静态内容)用于本地开发工作以禁用所有浏览器缓存:
upstream testCom
{
server localhost:1338;
}
server
{
listen 80;
server_name <your ip or domain>;
location / {
# proxy_cache datacache;
proxy_cache_key $scheme$host$request_method$request_uri;
proxy_cache_valid 200 60m;
proxy_cache_min_uses 1;
proxy_cache_use_stale updating;
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
proxy_ignore_headers Set-Cookie;
userid on;
userid_name __uid;
userid_domain <your ip or domain>;
userid_path /;
userid_expires max;
userid_p3p 'policyref="/w3c/p3p.xml", CP="CUR ADM OUR NOR STA NID"';
add_header Last-Modified $date_gmt;
add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;
proxy_pass http://testCom;
}
}
我知道这个问题有点老,但我建议在 javascript 的 url 中使用一些缓存制动散列。这在生产和开发过程中都非常有效,因为您可以拥有无限的缓存时间和发生变化时的即时更新。
假设你有一个javascript文件/js/script.min.js, 但是在引用的 html/php 文件中你不使用实际路径但是:
<script src="/js/script.<?php echo md5(filemtime('/js/script.min.js')); ?>.min.js"></script>
所以每次文件更改时,浏览器都会得到一个不同的 url,这反过来意味着它不能被缓存,无论是在本地还是在其间的任何代理上。
要完成这项工作,您需要 nginx 将对 /js/script.[0-9a-f]{32}.min.js 的任何请求重写为原始文件名。就我而言,我使用以下指令(也适用于 css):
location ~* \.(css|js)$ {
expires max;
add_header Pragma public;
etag off;
add_header Cache-Control "public";
add_header Last-Modified "";
rewrite "^/(.*)\/(style|script)\.min\.([\d\w]{32})\.(js|css)$" /$1/$2.min.$4 break;
}
我猜 filemtime 调用甚至不需要访问服务器上的磁盘,因为它应该在 linux 的文件缓存中。如果您有疑问或静态 html 文件,您还可以使用固定的随机值(或增量或内容哈希),当您的 javascript / css 预处理器完成或让您的 git 钩子之一更改它时更新它。
理论上,您也可以使用缓存破坏程序作为虚拟参数(如 /js/script.min.js?cachebreak=0123456789abcfef),但由于“?”,文件至少不会被某些代理缓存。
缓存是个好东西,但有时无论如何你都想重新加载文件。
所以为此(在生产环境中)我们只定义文件版本并定义浏览器应尽可能长时间地缓存该文件。
例。我的文件.v11.js
对于调试环境,您只需在浏览器中禁用缓存并在页面上工作时按强制重新加载。