React & nginx 路由到子目录

IT技术 reactjs nginx
2021-04-22 04:08:00

刚开始使用 React。我创建了一个应用程序,create-react-app它应该运行一段sub-directory时间,同时对不同的路径进行 API 调用。

react应用程序:

服务器上的位置: /var/www/myapp/build

端点: https://foo.example.com/analytics

数据 API 端点: https://foo.example.com/api/data

Nginx 设置

    location /analytics {
           root /var/www/myapp/build;
           try_files $uri /index.html;
    }

"homepage":"https://foo.example.com/analytics"在客户端的 中设置package.json,所有资源路径似乎都是正确的(即https://foo.example.com/analytics/static/...),但是在检查网络时没有请求.../api/data显示在我的浏览器的网络检查器中,并且应用程序没有正确生成。

App's API call(fetch('https://foo.example.com/api/data')而不是fetch('/api/data')) 中使用绝对路径似乎也无济于事。

而不是当我设置"homepage":"."package.json,改变它的Nginx的配置担任服务器的根目录,应用程序的作品reactbuild目录。

server {
        root /var/www/myapp/build;
}

但是,在这种情况下,该应用程序也可以在 下使用https://foo.example.com,这是我不想要的。

我强烈怀疑这与路由有关,但无法弄清楚如何解决它。所以任何帮助将不胜感激!

--- 编辑/解决方案 ---

我怀疑这是最直接的解决方案,但以下设置对我有用:

react应用

package.json"homepage":"./analytics"运行前设置npm run build

Nginx 配置:

    location =  /analytics {

            root /var/www/myapp/build;
            try_files /index.html =404;
    }

    location ~ ^/analytics(.*) {

            root /var/www/myapp/build;
            try_files $1 $1/ /index.html =404;
    }

我的理解是,使用的初始设置try_files $uri是在根目录中/var/www/myapp/build查找完整 uri 的文件,而不仅仅是后面的路径/analytics例如,当请求../analytics/css/styles.css时,它会检查一个/var/www/mayapp/build/analytics/css/styles.css不存在的文件(或目录)是否可用,因此它继续index.html作为后备。因此,正则表达式解决方法。

不过,改进此解决方案的反馈仍然非常受欢迎。

3个回答

我正在努力解决同样的问题。最后,我能够使用官方文档和答案组合解决它:

假设:

  • 您的 React 应用程序基于create-react-app包(您正在使用react-router-dom)。
  • 您正在使用 Nginx,并且根路径正被另一个服务(甚至是另一个 React/Gatsby 应用程序,这是我的情况)使用。
  • 您希望在子目录中部署 React App,并能够从该子目录提供 React App 的所有静态数据。

react应用程序更改

基于官方文档

  1. 更新您BrowserRouter的加入basename例子:<BrowserRouter history={history} basename="/webapp">
  2. 指定homepage你的package.json例子:"homepage": "/webapp"
  3. 如果您通过相对路径引用静态文件,则应将子目录添加到该引用中。例子:src="/static/logo/logo.png"变成src="/webapp/static/logo/logo.png".

Nginx 变化

location ^~ /webapp {
   alias /var/www/myapp/build;
   try_files $uri $uri/ /webapp/index.html;
}
非常感谢。我也赞同 Ursin 的评论。
2021-06-14 04:08:00
感谢您提供此分步解决方案。如果有人想知道:您不需要使用路由器的任何东西,只需将 <BrowserRouter basename="/webapp"> 添加到您的根应用程序就足够了。
2021-06-15 04:08:00

下面是一个 nginx 位置配置的例子:

location ^~ /analytics  {
    alias /var/www/myapp/build;

    subs_filter href="/ href="http://foo.example.com/analytics;
    subs_filter src="/ src="http://foo.example.com/analytics;
}
  • location设置为^~ /analytics,意味着在位置括号创建的规则将成为有效的,当有人访问http://foo.example.com/analytics
  • alias设置创建react的-App网站的静态生成文件夹/var/www/myapp/build当访问者点击您的子目录 url foo.example.com/analytics 时,将提供该服务
  • 接下来,这两subs_filter行用新的完整 URL替换以React 应用程序的主目录开头的任何对hrefsrcurl 的引用/这将确保 NGINX 正确定位和提供所有 CSS 和 JS 文件。

最后一点,在 Create-React-App 的情况下,createBrowserHistory您的react-router中的任何引用都需要替换为createHashHistory,因为浏览器历史记录不适用于上述 NGINX 配置。

您的回答缺少一些引号
2021-05-30 04:08:00
原来域关闭,这里是一个Wayback机器链接:web.archive.org/web/20191001055835/http://graemefulton.com/code/...
2021-06-01 04:08:00
^ sub_filter href="/" href="https://api.example.com/some-sub-dir";-没有ssub(NOT subs)[编辑:嘿,这个工作我活泉!我到处找]
2021-06-09 04:08:00
感谢您的回复。我试图复制你的 nginx 位置配置。无论是在你写的时候还是用右引号(例如subs_filter href="/"..),但在这两种情况下,我在运行时都会出错nginx -t
2021-06-12 04:08:00
在答案中引用原始资料时参考原始资料总是好的。这是graemefulton.com/code/snippet/...
2021-06-13 04:08:00

我的网站名为 derekdawsonspersonalwebsite.com,我想提供我在 derekdawsonspersonalwebsite.com/metronome/ 上制作的 React 应用程序

我通过执行以下操作得到了这个工作:

  1. 添加"homepage": "/metronome",package.json文件中
  2. 如果您使用的是react-router<BrowserRouter basename="/your_subdirectory">,请在我的情况下添加
<BrowserRouter basename="/metronome">
    <div>
        <nav>
            <Link to="/"></Link>
        </nav>
        <Switch>
            <Route exact path="/" component={Metronome} />
        </Switch>
    </div>
</BrowserRouter>
  1. yarn run build
  2. 我将构建目录的内容上传到我服务器上的这个位置 /var/www/personalwebsite.com/metronome
  3. 这是我的服务器块的/etc/nginx/sites-available/personalwebsite.com样子
server {
    listen 443 ssl;

    server_name derekdawsonspersonalwebsite.com www.derekdawsonspersonalwebsite.com;
    ssl_certificate /home/derek/ssl/derekdawsonspersonalwebsite.com_chain.crt;
    ssl_certificate_key /home/derek/ssl/derekdawsonspersonalwebsite.com_tld.key;

    location / {
        root /var/www/personalwebsite.com;
        index index.html;
    }

    location /metronome {
        root /var/www/personalwebsite.com;
        index index.html;
    }
}

server {
    listen 80 default_server;
    server_name derekdawsonspersonalwebsite.com www.derekdawsonspersonalwebsite.com;
    return 301 https://$host$request_uri;
}
在 Metronome 之后您没有使用嵌套目录。如果你这样做,你会得到一个错误。
2021-05-28 04:08:00