如何为 React 路由设置 apache 服务器?

Posted

技术标签:

【中文标题】如何为 React 路由设置 apache 服务器?【英文标题】:How to setup apache server for React route? 【发布时间】:2017-10-17 17:15:33 【问题描述】:

我的 react 应用程序在我的本地开发服务器上运行良好,但是当我将生产就绪文件直接转储到 Apache 的 htdocs 目录中时它不起作用:

这是我所拥有的:

/var/www/index.html
/var/www/bundle.js

我有

DocumentRoot /var/www

在 /etc/apache2/sites-available/000-default.conf 中

事实上, 1)。当我访问 http://...com/ 时将我路由到登录页面 2)。点击链接后

<Link to="main"><button>Log In</button></Link>

浏览器位置字段中的内容变为:

http://...com/main

3)。现在,如果我重新加载此 url (http://...com/main),我得到了

The requested URL /main was not found on this server

我在 React 中的巡演:

    <Router history=browserHistory >
      <Route path="/" component=TopContainer>
          <IndexRoute component=Login />
          <Route path='main' component=MainContainer />   
      </Route>
</Router>

我在 apache 配置中还缺少什么?

谢谢

【问题讨论】:

你应该选择一个正确的答案。感谢您的提问。 【参考方案1】:

通过添加以下 Rewrite* 行来更改 VirtualHost 配置(通常在 /etc/httpd/conf.d\vhosts.conf 中找到):

<VirtualHost *:8080>
  ServerName example.com
  DocumentRoot /var/www/httpd/example.com

  <Directory "/var/www/httpd/example.com">
    ...

    RewriteEngine on
    # Don't rewrite files or directories
    RewriteCond %REQUEST_FILENAME -f [OR]
    RewriteCond %REQUEST_FILENAME -d
    RewriteRule ^ - [L]
    # Rewrite everything else to index.html to allow html5 state links
    RewriteRule ^ index.html [L]
  </Directory>
</VirtualHost>

这告诉 Apache 提供任何存在的文件,但如果它们不存在,则只提供 /index.html 而不是 404: not found

Apache 参考:Configuring Apache Virtual Hosts

react-router历史参考:Configuring Your Server

感谢从here盗取的完整答案

【讨论】:

为了进一步解释这是做什么的,如果 RewriteCond 匹配(即文件或目录存在),那么 RewriteRule ^ - [L] 表示“什么都不做”。否则,它会将任何其他流量重定向到 index.html。 如果我只想重写目录但文件上有 404,这条规则会怎样? 谢谢@Hinrich,这个解决方案在 ubuntu 20.04 中适用于 react 16.13.0 和 react-router-dom 5.1.2。【参考方案2】:

上述解决方案也适用于 Ubuntu,但我在使用它时遇到了一些困难,所以这里是使它工作的必要步骤。

需要放置上述配置的文件位置在

/etc/apache2/sites-enabled

默认是

/etc/apache2/sites-enabled/000-default.conf

那么你需要确保 RewriteEngine 正在运行(否则重启 Apache 服务器时会报错)。

sudo a2enmod rewrite

最后,重启 Apache 服务器

sudo /etc/init.d/apache2 restart

现在,它应该可以工作了。

当你使用默认配置时(网站根在/var/www/html下),那么你需要做的就是放置

<Directory "/var/www/html">
    RewriteEngine on
    # Don't rewrite files or directories
    RewriteCond %REQUEST_FILENAME -f [OR]
    RewriteCond %REQUEST_FILENAME -d
    RewriteRule ^ - [L]
    # Rewrite everything else to index.html to allow html5 state links
    RewriteRule ^ index.html [L]
</Directory>

&lt;VirtualHost ...&gt;下的上述文件

【讨论】:

谢谢这个帮了我很多,节省了我的时间。 对于谷歌员工,&lt;Directory "/var/www/html"&gt;&lt;/Directory&gt; 是使其正常工作所必需的。 在使用 .htaccess 文件之前,我们需要更新 AllowOverride 设置以便能够覆盖 Apache 指令。编辑文件/etc/httpd/conf/httpd.conf 找到&lt;Directory /var/www/html&gt; 部分并将AllowOverride 指令从None 更改为All 我将您的解决方案与@VLRoyrenn 的答案结合起来,它在 Ubuntu 上对我有用。 非常感谢。【参考方案3】:

如果您必须使用 .htaccess 和子目录,那么以下对我有用。

Options -MultiViews
RewriteEngine On
RewriteCond %REQUEST_FILENAME !-f
RewriteRule ^ index.html [QSA,L]

【讨论】:

【参考方案4】:

什么对我有用,在这里呼应了许多答案和 cmets:

    sudo a2enmod rewrite 打开/etc/apache2/apache2.conf 将路径粘贴到您的根目录中:
<Directory "/var/www/PATH_TO_YOUR_ROOT">
    RewriteEngine on
    # Don't rewrite files or directories
    RewriteCond %REQUEST_FILENAME -f [OR]
    RewriteCond %REQUEST_FILENAME -d
    RewriteRule ^ - [L]
    # Rewrite everything else to index.html to allow html5 state links
    RewriteRule ^ index.html [L]
</Directory>
    sudo service apache2 restart

粘贴到特定于站点的 conf 文件中没有像之前的答案所建议的那样工作。

【讨论】:

【参考方案5】:

目前发布的解决方案似乎都没有解决丢失资源错误地返回 200 而不是 404 的问题,这会使某些文件丢失时的调试变得相当烦人。

我的解决方案是查看请求期望接收的资源类型,因为浏览器在导航到页面时会要求 HTML(Firefox 要求text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8),但在初始加载后访问资源时不会(JS 文件通过&lt;script&gt; 导入或作为ES6 模块请求*/*,CSS 文件请求text/css,*/*;q=0.1,通过fetch() API 访问JSON 将指定application/json, text/plain, */* 等等)。通过依赖该假设,可以将 Apache 配置为在尝试访问不存在的文件(例如仅在单页应用程序中有效的路由)时为单页应用程序提供服务,而无需在所述 SPA 要求时发送它已重命名的 CSS 文件或缺少 JSON 文件。

编辑: MDN has a list of common values 用于 Accept 标头。

<Directory  "/var/www/httpd/example.com">
    RewriteEngine on

    # Browsers will specifically ask for HTML (among other things) on initial page load
    # That is, if the *user* tries to access a *nonexisting* URL, the app is loaded instead
    # but if a webpage attempts to load a missing resource it will return 404.
    # (You can still go to /myreactapp/favicon.ico, but a missing /myreactapp/favicon.png resource won't return 200)

    # if (HTTP_ACCESS.contains('text/html') && file_not_exists(REQUEST_FILENAME))
    RewriteCond %HTTP_ACCEPT text/html
    RewriteCond %REQUEST_FILENAME !-f
        RewriteRule ^ index.html [last]

    # Any ressources loaded by index.html should behave correctly (i.e: Return 404 if missing)
    RewriteRule ^ - [last]

    AllowOverride None
    Options FollowSymLinks Multiviews 
    Require all granted
</Directory>

【讨论】:

我将您的解决方案与@MatusDubrava 的答案结合起来,它在 Ubuntu 上对我有用。 将前 5 行(RewriteEngine、RewriteConds 和 RewriteRules)添加到我的应用程序 html_public 文件夹的 .htaccess 中,这就足够了。【参考方案6】:

谢谢!这对我有用。

如果您服务于多个站点(虚拟主机)以及 SSL 证书(SSL 是使用 certbot 制作的),我将粘贴我的配置,并将 http 重定向到 https

此设置适用于 Linode / Ubuntu

yoursite.com-le-ssl.conf

<IfModule mod_ssl.c>
<VirtualHost *:443>
  # Admin email, Server Name (domain name), and any aliases
  ServerAdmin webmaster@yoursite.com
  ServerName  yoursite.com
  ServerAlias www.yoursite.com

  # Index file and Document Root (where the public files are located)
 DirectoryIndex index.html index.php
  DocumentRoot /var/www/html/yoursite.com/public_html 
<Directory  "/var/www/html/yoursite.com/public_html">
    RewriteEngine on

    # Browsers will specifically ask for HTML (among other things) on initial page load
    # That is, if the *user* tries to access a *nonexisting* URL, the app is loaded instead
    # but if a webpage attempts to load a missing resource it will return 404.
    # (You can still go to /myreactapp/favicon.ico, but a missing /myreactapp/favicon.png resource won't return 200)

    # if (HTTP_ACCESS.contains('text/html') && file_not_exists(REQUEST_FILENAME))
    RewriteCond %HTTP_ACCEPT text/html
    RewriteCond %REQUEST_FILENAME !-f
        RewriteRule ^ index.html [last]

    # Any ressources loaded by index.html should behave correctly (i.e: Return 404 if missing)
    RewriteRule ^ - [last]

    AllowOverride None
    Options FollowSymLinks Multiviews 
    Require all granted
</Directory>
  # Log file locations
  LogLevel warn
  ErrorLog  /var/www/html/yoursite.com/log/error.log
  CustomLog /var/www/html/yoursite.com/log/access.log combined
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/yoursite.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/yoursite.com/privkey.pem
</VirtualHost>
</IfModule>

【讨论】:

【参考方案7】:

在 ubantu 服务器上修复了 React 路由问题

解决方案:

    使用控制台打开文件。

如果您使用 SSL 纳米 /etc/apache2/sites-available/000-default-le-ssl.conf

添加以下行

================================================ ======================================

DocumentRoot /var/www/project 重写引擎开启 RewriteCond %HTTP_ACCEPT 文本/html RewriteCond %REQUEST_FILENAME !-f RewriteRule ^ index.html [最后] RewriteRule ^ - [最后一个]

AllowOverride None
Options FollowSymLinks Multiviews 
Require all granted

【讨论】:

【参考方案8】:

进入这个目录

    /etc/apache2/sites-available

    打开文件:000-default.conf

    更改权限:777

    在文件底部粘贴代码

RewriteEngine on 

# Don't rewrite files or directories 

RewriteCond %REQUEST_FILENAME -f [OR] 

RewriteCond %REQUEST_FILENAME -d 

RewriteRule ^ - [L] 

# Rewrite everything else to index.html to allow html5 state links 

RewriteRule ^ index.html [L] 

    重启服务器

【讨论】:

将权限更改为 777 并不是一个好建议,即使它可以让部署工作。 投反对票,因为它建议将文件权限更改为 777

以上是关于如何为 React 路由设置 apache 服务器?的主要内容,如果未能解决你的问题,请参考以下文章

如何为运行 WHM 的服务器设置默认的 Apache 登录页面?

如何为在 localhost:3000 上运行的 Create-React-App 设置代理通过 NGINX

如何为所有路径设置代理位置,除了一些使用 apache2 的路径? [关闭]

如何为生产者设置路由键

如何为 Jenkins 服务器做 Apache2 托管

如何为 React 设置 Sublime Text 3?