nginx的使用非常广泛,但是其实它的配置方面并不是特别友好,换句话说nginx配置方面的坑其实还挺多,易用性不是那么强,但是真正配置好了,就会感觉挺好用了。nginx中有一个try_files配置,很多人在配置location的时候,没有加上这句配置,就会导致一些莫名其妙的问题。最典型的问题就是比如vue单页面项目,打包后通过nginx来映射,如果用户在点击浏览器刷新按钮,那么会出现一种情况就是,刷新后会显示404 not found,或者301重定向到了某个静态页面中去了。这些bug都是因为没有配置try_files的原因。

try_files的一般用法

1
2
3
4
5
location / {
root .../dist
index ...index.html
try_files $uri $uri/ /index.html;
}

上面这段代码表明,该应用打包后的文件夹是dist,该应用的入口页面是其中的index.html页。那么try_files $uri $uri/ /index.html代表什么呢。
首先要解释一个知识,就是如果你是vue等框架的单页面应用,它的路由是由自身的js来控制跳转的,nginx只负责第一次访问时将入口index.html和其中的js发送给浏览器,之后的内部跳转就由js在前端完成了。然而如果是点击浏览器刷新,或者直接在地址栏输入url来访问,此时就无法像正常流程那样进入到index中,所以路由也就出现问题,从而报404错误。

当我们加了try_files之后,用户如果是点击浏览器刷新,或者直接在地址栏输入url来访问某页面时,nginx会去dist文件夹中寻找能够匹配的页面名称,此时对于单页面应用肯定是找不到的,所以第二步nginx会找拥有该页面相同名称的文件夹,一般也是找不到的,除非你使用了预渲染之类的插件,将静态页面生成到了dist文件夹中,此时就会找到页面相同名称文件夹,然后nginx就会把这个文件夹中的页面发送给浏览器。

如果没有使用预渲染之类的插件,肯定找不到该页面对应的文件夹,此时nginx会把index.html这个入口文件发送给浏览器。

因此,“try_files”表明找不到对应路径时开始寻找,第一个参数“$uri”表明先找相同名字的文件,第二个参数“$uri/”表明再找相同名字的文件夹,第三个参数“index.html”表明如果文件和文件夹都没找到,那么就返回index入口页面。
这样一来,就保证了绝不会发生刷新或者直接输入url导致的404错误了。如果想要不发生301重定向,可以将“$uri/”删除,这样就不会寻找与页面相同名称的文件夹,也就不会读取文件夹里面的html文件,从而不存在301重定向问题了。

提示:修改配置应该在nginx/conf/nginx.conf文件中进行,要注意保存。在有些情况下,编辑器可能会改变nginx.conf文件的编码格式,导致配置文件可能失效,所以最好保证编辑器将nginc.conf文件保存为utf8格式。