【问题标题】:React & nginx routing to subdirectoryReact 和 nginx 路由到子目录
【发布时间】:2018-11-08 11:43:26
【问题描述】:

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

反应应用:

服务器上的位置:/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;
    }

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

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

当我在 package.json 中设置 "homepage":"." 并更改 Nginx 配置以在服务器根目录上提供 react 构建目录时,该应用程序可以正常工作。

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

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

我强烈怀疑这与路由有关,但不知道如何解决。因此,我们将不胜感激任何帮助!

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

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

反应应用

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

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 作为后备。因此,正则表达式解决方法。

尽管如此,我们仍然非常欢迎您提出改进此解决方案的反馈。

【问题讨论】:

    标签: reactjs nginx


    【解决方案1】:

    我也在为同样的问题而苦苦挣扎。最后我能够使用官方文档和答案组合来解决它:

    假设:

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

    响应应用更改

    基于official documentation

    1. 通过添加basename 来更新您的BrowserRouter。示例:<BrowserRouter history={history} basename="/webapp">
    2. 在您的package.json 上指定homepage。示例:"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 的评论。
    • 不是所有的英雄都穿斗篷...
    【解决方案2】:

    这里是一个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 设置为 create-react-app 站点 /var/www/myapp/build 的静态构建文件夹。当访问者点击您的子目录 url foo.example.com/analytics
    • 接下来,两个 subs_filter 行将所有以 React 应用程序的主目录 / 开头的对 hrefsrc url 的引用替换为新的完整 URL。这将确保 NGINX 正确定位和提供所有 CSS 和 JS 文件。

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

    【讨论】:

    • 感谢您的回复。我试图复制您的 nginx 位置配置。无论是你写的还是右引号(例如subs_filter href="/" ..),但在这两种情况下,我在运行nginx -t时都会出错
    • 您的答案缺少一些引号
    • 在答案中引用原始来源总是很好。这里是graemefulton.com/code/snippet/…
    • 原域名挂了,这里是回路机链接:web.archive.org/web/20191001055835/http://graemefulton.com/code/….
    • ^ sub_filter href="/" href="https://api.example.com/some-sub-dir"; - 在sub 中没有s(不是subs)[编辑:嘿,这对我有用!我到处找]
    【解决方案3】:

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

    我通过执行以下操作来完成这项工作:

    1. "homepage": "/metronome", 添加到package.json 文件中
    2. 如果您使用的是 react 路由器,请添加 <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;
    }
    

    【讨论】:

    • 您没有在节拍器之后使用嵌套目录。如果你这样做,你会得到一个错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-15
    • 2018-01-28
    • 1970-01-01
    • 2020-09-09
    相关资源
    最近更新 更多