try_files是动静分离中“静态优先、动态兜底”的最轻量可靠机制,按序检查文件/目录存在性,全部失败时执行以/或@开头的兜底项,需注意root/alias区别、路径相对性、命名location定义位置及循环重写规避。

在动静分离架构下,try_files 是实现“静态优先、动态兜底”最轻量且可靠的机制。它不触发外部重定向,不依赖 rewrite,所有判断都在一次请求内完成,天然适配 SPA、混合站点和缓存降级场景。
核心配置逻辑:按序检查 + 明确兜底
try_files 后面的参数用空格分隔,Nginx 会严格按顺序检查每个路径是否为真实存在的文件或目录(注意:只检查存在性,不自动补扩展名)。只要某一项命中,就立即返回对应资源;全部失败时,才执行最后一个参数——它必须是以下二者之一:
- 以 / 开头的 URI:触发内部重写,重新进入 location 匹配流程(需防循环)
- 以 @ 开头的命名 location:直接跳转到该块,不再匹配其他 location
典型动静分离兜底组合
根据后端类型选择合适兜底目标:
-
PHP 站点(如 WordPress、ThinkPHP):
try_files $uri $uri/ /index.php?$query_string;
→ 先找静态文件,再找目录,最后交由 index.php 处理动态逻辑 -
Java/Tomcat 或 Python/Gunicorn 后端:
try_files $uri $uri/ @backend;
→ 最后跳转到命名 location,在其中配置proxy_pass -
前端单页应用(Vue/React):
try_files $uri $uri/ /index.html;
→ 静态资源直出,前端路由全部回退到 index.html 由 JS 解析
关键细节与避坑要点
看似简单,但几个细节决定成败:
-
root 和 alias 不可混用:若 location 使用
alias,$uri的拼接规则不同,容易导致路径错位;建议静态服务统一用root+ 标准 location -
不能写绝对路径:如
try_files /var/www/file.js …是非法的,所有路径都相对于root或alias定义的根 - 命名 location 必须定义在同级 server 或 http 块中,否则会报 “unknown directive” 错误
-
避免循环重写:若兜底 URI(如
/index.php)又被当前 location 匹配,就会无限循环;可通过更精确的正则 location 或独立 path 分离来规避
进阶:多级 fallback 与缓存协同
当需要更细粒度控制时,可链式设置 fallback:
-
try_files $uri /cdn/$uri /fallback.html;
→ 先查本地,再查 CDN 镜像目录,最后兜底页面 - 配合静态缓存头:
在匹配图片、JS、CSS 的 location 中加expires 1y;和add_header Cache-Control "public, immutable";,让浏览器长期缓存,真正降低回源压力











