如何设置 NGINX 以部署不同的单页应用程序(SPA 的...即静态文件),具体取决于位置(在相同的 server_name 下)和子路由

Posted

技术标签:

【中文标题】如何设置 NGINX 以部署不同的单页应用程序(SPA 的...即静态文件),具体取决于位置(在相同的 server_name 下)和子路由【英文标题】:How to setup NGINX to deploy different Single Page Apps (SPA's... i.e static files) depending on location (under same server_name) with subroutes 【发布时间】:2015-10-09 18:04:43 【问题描述】:

我的目标是在同一个域下设置两个不同的单页应用程序 (SPA),我们在其中显示与请求的位置/路径相对应的 SPA。我还想默认为 / 位置上的两个 SPA 之一。而且.. 如果有人在浏览器中输入 url,我希望 SPA 附加的 html5 历史位置路径实际路由到正确的位置。

举个例子更容易解释。

例子:

用户导航到 mydomain.com/app 并且服务器在 /home/user/app/dist 下提供内容(它有一个 index.html 和所有 js/css 资产)(使用 linux 所以 /home/user 只是我的主目录路径)。

用户导航到 mydomain.com/auth 并且服务器在 /home/user/auth/dist 下提供内容

用户导航到 / 并且服务器在 /home/user/auth/dist 下提供内容(默认 /navs 到 auth)

用户导航到 mydomain.com/auth/login 服务器再次提供 /home/user/auth/dist 文件夹下的内容 但 url 保持 mydomain.com/auth/login 以便 auth SPA 可以用作路由

用户导航到 mydomain.com/auth/signup 服务器再次提供 /home/user/auth/dist 文件夹下的内容 再次,url 保持 mydomain.com/auth/login 以便 auth SPA 可以用作路由

用户导航到 mydomain.com/app/home 并且服务器在 /home/user/app/dist 下提供内容

我已经尝试过 root/alias/rewrite/regex/=/^~ 规则。我正在尝试更深入地了解 nginx 设置,但与此同时,这是我目前所拥有的:

server 
listen [::]:80 default_server;
listen 80;
server_name mydomain.com 127.0.0.1;    # Make it serve in mydomain.com

# ^~ rules stop matching after the exact match 
location ^~ /app                      # if location start matches /app
  alias /home/user/app/dist;
  index index.html;
  try_files $uri $uri/ index.html =404;
                                      # if location start matches app/lobby
location ^~ /app/home 
  alias /home/user/app/dist;
  index index.html;
  try_files $uri $uri/ index.html =404;


# you can see that I need to add a new one per each client js app route
location ^~ /app/home/visitor 
  alias /home/user/app/dist;
  index index.html;
  try_files $uri $uri/ index.html =404;


location ^~ /auth/login 
  alias /home/user/auth/dist;
  index index.html;
  try_files $uri $uri/ index.html =404;

location ^~ /auth 
  alias /home/user/auth/dist;
  index index.html;
  try_files $uri $uri/ index.html =404;


# Rewrites / to auth, appending whatever params to path
#   var (for the client to consume)for now
location / 
  rewrite ^/(.*) /auth?path=$1 last;





它应该在 /dist 文件夹下找到一个 index.html

我想使用正则表达式或位置匹配,让客户端 js 应用程序捕捉到匹配的其余部分,这样我就不必为每个路由添加新规则(这个应用程序实际上有嵌套的状态路由)。我知道位置 ^~ 修饰符在匹配特定规则后停止,但我无法让它以任何其他方式工作。如果我不使用修饰符、正则表达式位置匹配或 = 修饰符...我只会从 nginx 收到 404、403 和 500 响应。

另外,如果我停止使用 alias/rewrite 并使用 root 关键字,它会尝试在 dist 文件夹下查找 /app 或 /auth 实际文件夹,这确实不应该(例如 if /home/user/auth /dist/auth 文件夹存在)。

我还让客户知道每个 SPA 的基本目录是什么,例如 basedir ="app"(用于应用程序)和 basedir="auth" 用于身份验证。

我认为我的重写是错误的,或者我需要更多的重写,或者额外的规则来使事情更通用。

我该怎么做呢?某种示例配置将不胜感激。谢谢。

附:如果有人好奇,我正在使用 Ember 和 Ember-cli。这会生成带有已构建应用程序的 dist/ 文件夹,并且还可以允许诸如 http://www.mydomain/app/home/visitor/comments/new 之类的路由,这就是为什么对每个路径进行硬编码没有意义(并且该应用程序仍在开发中,还有更多路由!)。

编辑

我也试过这个,我在 /app 和 /auth 路径中都得到了 404:

server 
listen [::]:80 default_server;
listen 80;
server_name localhost mydomain.com 127.0.0.1;

index index.html;

location /app 
  root /home/user/app/dist;
  try_files $uri $uri/index.html index.html;


location /auth 
  root /home/user/auth/dist;
  try_files $uri $uri/index.html index.html;



【问题讨论】:

您使用 ipv6only 设置是否有原因? @Hevlastka 不是真的。我想复制并粘贴部分配置。让我删除它。 我删除了它@Hevlastka,并测试了配置。不会改变任何东西。但以防万一。 你试过location /auth alias /home/user/auth/dist/; 吗(抱歉格式化!) @Hevlastka 也许。我已经尝试了很多东西。让我再试一次(以防万一),我会告诉你结果。 【参考方案1】:

首先,请确保您在 sites-enabled 中没有 default 配置,这有时可能会导致意外行为。

编辑: 最终配置如下

server 
  listen [::]:80 default_server;
  listen 80;
  server_name localhost mydomain 127.0.0.1;

  location /app 
    alias /home/user/app/dist/;
    index index.html;
    try_files $uri $uri/ index.html =404;
  

  location /auth 
    alias /home/user/auth/dist/;
    index index.html;
    try_files $uri $uri/ index.html =404;
  

  location / 
    rewrite ^/(.*) /auth?$1 last;
  

this question 和 nginx docs 也值得一试,它们更多地解释了 root 和别名之间的区别。

【讨论】:

让我仔细检查一下这个是否有效(别名路径上没有斜杠),我会将其标记为已接受。 我错过了别名上的 / 斜杠。此解决方案之所以有效,是因为它允许用户导航到 mydomain.com/app、mydomain.com/app/home、mydomain.com/auth、mydomain.com/auth/login、mydomain.com 并仍然访问静态文件(css /js) 并以正确的方式索引,即使我的客户端应用程序将路径附加到 url。感谢您的帮助@Hevlastka。 非常有用。小提示:如果您知道index.html 将始终存在,那么就不需要=404 我已将 Angular 生产代码复制到其中一个目录。默认 index.html 页面工作正常(domain.com/angularPages/),但是当我尝试 domain.com/angularPages/login 时,它说 404 not found.

以上是关于如何设置 NGINX 以部署不同的单页应用程序(SPA 的...即静态文件),具体取决于位置(在相同的 server_name 下)和子路由的主要内容,如果未能解决你的问题,请参考以下文章

带有 HTML5 应用缓存的单页应用的 Nginx 配置

使用 Express 的单页应用程序 React 路由 URL。但不要使用 create-react-app 或 Heroku 之类的部署服务

在具有不同主页的单页应用程序中路由

颤振如何与单页网页和不同的路由网址一起工作?

使用 AngularJS 和 Spring Security 的单页应用程序中需要 AntMatchers

具有 REST API 架构的单页应用程序