我有以下的nginxconfiguration:
server { listen 8080; root /site_root/web; index index.html; server_name www.mysite.com; location / { try_files $uri @rewriteapp; } location @rewriteapp { rewrite ^(.*)$ /app.php/$1 last; } # add headers to static files location ~* \.(?:ico|css|js|gif|jpe?g|png|svg|woff|ttf|eot)$ { expires 365d; add_header Pragma public; add_header Cache-Control "public"; } location ~ \.php { fastcgi_split_path_info ^(.+\.php)(/.*)$; include fastcgi_params; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param HTTPS $https; fastcgi_pass unix:/var/run/php-fpm-www.sock; } }
问题这是一个标准的PHP应用程序,前面的控制器和一些静态资产(js / css等)作为文件坐在文件系统上(为了参数,这些文件的位置是'/ site_root / web / assets')。
上述configuration的目的是为这些静态文件添加“max-age”标头,以允许浏览器caching它们。 这适用于文件系统上存在的所有文件。 不过,我有一些dynamic生成的资产,需要通过PHP('/site_root/web/assets/dynamic/file.uk.js','/site_root/web/assets/dynamic/file.us.js', '/site_root/web/assets/variable/variable.uk.js')。
问题是,包含位置指令“添加标头到静态文件”导致这些dynamic文件到404。我怎么能(按照每个解决scheme的理想顺序):
更改位置指令以排除服务器上不存在的文件(使用try_files / internal?)
更改位置指令以排除匹配的path(白名单,例如'dynamic | variable')
这归结于nginx将只使用一个位置块的事实。 其他位置块中的任何内容都将被忽略。 在问题中,与“静态文件”位置块匹配的任何请求,文件是否存在,将仅由该位置块处理。 每当有一些不明确的地方,我发现一个有用的debugging技术:
location /something-else { add_header "section" "something else location"; # ^ if this location block is used, that header is in the output ... }
在响应的头文件中,从匹配的块中添加的头文件将包含在内:
$ curl -I "http://nginx.h5bp.dev/something" ... section: something location # <- like so
有很多解决scheme,你可能会发现这个参考资料有用的阅读。 有一点要记住的是,nginx的目的是用于前缀路由 – 这使得nginx和你的生活变得简单。
所以,如果你能做到这一点:
location ~ ^/(css|images|js)/ { expires 365d; add_header Pragma public; add_header Cache-Control "public"; } location ~ \.php { ... }
那将是最佳的解决scheme。 如果需要的话,也可以使用嵌套位置块的扩展:
location ~ ^/(css|images|js)/ { location ~* \.(?:whatever|ext)$ { expires 365d; add_header Pragma public; add_header Cache-Control "public"; } } location ~ \.php { ... }
在这个问题上,有一个位置块 – 所以这是一个明显的select,正如Micheal所说:
location ~* \.(?:ico|css|js|gif|jpe?g|png|svg|woff|ttf|eot)$ { try_files $uri @rewriteapp; # <- added expires 365d; add_header Pragma public; add_header Cache-Control "public"; } location ~ \.php { ... }
如果你有多个位置块,这是非常乏味的(尽pipe,也可能表明不使用nginxdevise)
将永远工作的设置,不pipe你的位置块看起来像是使用404前端控制器。 在你的情况下,这将意味着:
server { listen 8080; root /site_root/web; index index.html; server_name www.mysite.com; try_files $uri $uri/ @rewriteapp; error_page 404 = @rewriteapp location @rewriteapp { rewrite ^ /app.php/$request_uri last; } # add headers to static files location ~* \.(?:ico|css|js|gif|jpe?g|png|svg|woff|ttf|eot)$ { expires 365d; add_header Pragma public; add_header Cache-Control "public"; } location ~ \.php { fastcgi_split_path_info ^(.+\.php)(/.*)$; include fastcgi_params; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param HTTPS $https; fastcgi_pass unix:/var/run/php-fpm-www.sock; } }
或类似。 select适合您的解决scheme是最简单的。
你为什么不把它们传递给你的应用程序呢?
location ~* \.(?:ico|css|js|gif|jpe?g|png|svg|woff|ttf|eot)$ { try_files $uri @rewriteapp; #...everything else