侧边栏壁纸
  • 累计撰写 218 篇文章
  • 累计创建 59 个标签
  • 累计收到 5 条评论

Nginx:在单页面应用中配置 try_files

barwe
2022-06-20 / 0 评论 / 0 点赞 / 2,132 阅读 / 1,644 字
温馨提示:
本文最后更新于 2023-06-07,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

Nginx 部署单页面应用时,访问除了跟路由外的其他路由,提示找不到资源。

SPA 的单个入口

默认情况下,一个打包好的 Vue 应用结构如下:

html
|-- assets
|-- favicon.ico
|-- index.html

这个应用只提供了一个入口文件(index.html),它在 Nginx 中的 location 块一般长这样:

location / {
    root /usr/share/nginx/html;
    index index.html index.htm;
}

当我们访问该站点的一个资源时,如果访问的是根路径,例如http://127.0.0.1/,它将匹配上面的/块,然后 Nginx 去 root 指定的目录下获取资源(根路径对应的资源 URI 是/),即最终的资源路径为/usr/share/nginx/html/,这个路径以/结尾,表明它是一个目录,按照 index 的约定 Nginx 继续查找它下面的index.html文件或者index.htm文件,显然最后返回的是/usr/share/nginx/html/index.html文件。

如果我们访问http://127.0.0.1/favicon.ico,进入/块后其 URI 为favicon.ico,Nginx 会查找 root 下的favicon.ico文件,显然 Nginx 可以直接找到/usr/share/nginx/html/favicon.ico文件,所以这个请求也是可以正常完成的。

如果我们访问http://127.0.0.1/test,进入/块后其 URI 为test,Nginx 匹配不到$root/test文件,于是出现下面的结果:

image-20220620112925321

这种情况在单页面应用中十分常见,这是因为 Nginx 默认只查找文件(URI 不以/结尾)或者目录(URI 以/结尾)下的 index 文件。


try_files 的使用例子

try_files指令用在 server 块或者 location 块中,用来指定资源的查找顺序。官方提供了这样一个例子:

location /images/ {
    root /images;
    try_files $uri $uri/ /images/default.gif;
}

假如我们请求资源http://127.0.0.1/images/test.gif,在 server 全局块中其 URI 为/images/test.gif

如果这个 URI 被/images/块匹配,在块内部,其 URI 变为test.gif(去掉公共前缀后剩余部分仍可作为资源的标识符)。

Nginx 按照 try_files 指定的顺序搜索资源:

  1. 搜索的根目录是 server.root + location.root,例如/usr/share/nginx/html/images
  2. 首先搜索$uri,即搜索根目录下的test.gif文件,如果找到了则返回资源
  3. 然后搜索$uri/,即搜索根目录下的test.gif/子目录下的 index 文件,如果找到了则返回资源
  4. 最后直接返回images/default.gif文件

try_files 的详细用法

官方文档:http://nginx.org/en/docs/http/ngx_http_core_module.html#try_files

用法:

try_files file URI;
try_files file =CODE;

按照 file 指定的顺序检查资源文件是否存在,返回第一个查找到的资源文件。

查找过程只在当前块指定的目录下进行。

指定参数以/结尾以检查资源目录是否存在,例如$uri/

如果所有 file 都没有匹配上,try_files 的最后一个参数将作为兜底选项,它可以是:

  • 用于重定向的一个 URI:Nginx 将会查找另一个资源
  • 一个错误代码:Nginx 直接返回该代码对应的页面,例如 404
  • 一个代理服务器……
  • ……

解决方案

/块中配置 try_files 即可:

location / {
    root /usr/share/nginx/html;
    index index.html;
    try_files $uri $uri/ /index.html;
}
0

评论区