禁用 JavaScript 文件的 nginx 缓存

好吧,我几乎要放弃了,但是我怎样才能禁用从 Nginx 缓存 JavaScript 文件呢?我用的是 Nginx 的码头集装箱。当我现在更改 JavaScript 文件中的某些内容时,我需要多次重新加载,直到新文件出现。

我怎么知道它是 Nginx 而不是浏览器/插件?

Browser: 我在命令行上使用 curl来模拟请求,遇到了相同的问题。此外,我使用的是 CacheKiller插件,并在 Chrome 开发工具中禁用了缓存。

Docker: 当我连接到容器的 bash,并在更改文件后使用 cat时,我会立即得到正确的结果。

我把 sites-enablednginx.conf改成了这个(我在另一个 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;
}
145965 次浏览

expiresadd_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;
}

上面的代码不会缓存()中的扩展名。

我有以下 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 规范(请参阅改变格式)。

请记住,设置 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 的网址。这在生产环境和开发环境中都可以很好地工作,因为当发生更改时,您可以同时拥有无限的缓存时间和即时更新。

假设您有一个 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) ,但是由于“ ”,这个文件至少没有被一些代理缓存。