React 生产环境构建出现 404 页面未找到错误。

5

你好,我需要部署React应用程序。

为了实现这个目的,我运行命令:"npm run build"。

之后,在我的vhost.conf文件中,我添加了虚拟主机。

<VirtualHost *:80>
ServerName hello.local
DocumentRoot c:/wamp64/www/hello_world/build
<Directory  "c:/wamp64/www/hello_world/build">
             Options Indexes FollowSymLinks MultiViews
             AllowOverride All
             Require all granted
</Directory>

我还在etc/hosts中添加了hello.local

当然,我已经在httpd.conf中启用了mod rewrite

当我运行hello.local/时,我的React应用程序的主页能够正确显示,但是当我想进入react-router路径hello.local/example时,却收到了404未找到错误。请帮忙看看问题出在什么地方?是Apache配置有问题还是React-Router出现了一些错误?谢谢。

2个回答

22

这是SPA经常遇到的问题。在SPA中,大多数路由发生在客户端。在您的情况下,主要应该使用react-router来完成工作。由于整个js被捆绑为单个文件并在index.html中提供服务,因此您需要为服务器上不存在的所有路径提供index.html

您需要添加如下配置:

RewriteEngine On  
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]

RewriteRule ^ /index.html [L]
所以,如果在您的服务器上没有匹配的路径,index.html将被提供。然后JavaScript会执行,并且react-router(客户端路由)将接管并显示路由的正确组件。

对于大多数单页应用程序而言,这是正确的,其中路由发生在客户端。


是的先生,我已经用这种方式完成了,但这是最好解释的答案之一 :) 为你喝彩!@Panther SPA是什么? 这里有一个部署到生产环境的参考链接:https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#deployment - Juri Bojka
1
你太棒了!!!!!忘记将 .htaccess 文件放在根目录中了。现在一切都正常工作 :) - yanike
这正是我一直在寻找的!非常感谢您5天的研究!不过,当我的路由需要多个参数时(例如/test/id),仍然存在图像资源路径的问题,它会在/test/assets/img中查找路径... 这导致404错误。 - David C.
如何在使用单页应用程序时为不存在的路由返回404 HTTP状态码?例如,如果我为服务器上不存在的所有路径提供index.html,例如/path/which/does/not/exists/123,如果我已经使用200响应代码提供了index.html,那么我无法告诉客户端/path/which/does/not/exists/123不存在并返回404响应代码。我该怎么处理?我是否被迫使用另一种混合策略,并使用具有服务器端渲染的同构React,还是有一种方法可以在经典的单页应用程序中实现呢? - tonix
在单页应用程序中,路由对客户端代码是已知的。服务器将不知道所有可用路由的列表。因此,在路由方面也应该有显示404的逻辑。由于它是单页应用程序并且需要从服务器呈现,则应通过服务器端呈现来完成。 - Panther
1
你好@Panther,谢谢你的回答。但是我应该在哪个文件中添加这个配置呢? - Saddam Mohsen

0

在 Windows 10 上使用 web.config 配置 IIS

    <?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  https://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <system.webServer>
    <rewrite>
  <rules>
    <rule name="Imported Rule 1" stopProcessing="true">
      <match url="^" ignoreCase="false" />
      <conditions logicalGrouping="MatchAny">
        <add input="{DOCUMENT_ROOT}{URL}" matchType="IsFile" ignoreCase="false" />
        <add input="{DOCUMENT_ROOT}{URL}" matchType="IsDirectory" ignoreCase="false" />
      </conditions>
      <action type="None" />
    </rule>
    <rule name="Imported Rule 2" stopProcessing="true">
      <match url="^" ignoreCase="false" />
      <action type="Rewrite" url="/index.html" />
    </rule>
  </rules>
</rewrite>
  </system.webServer>
  <system.web>
    <customErrors mode="Off" />
    <httpRuntime targetFramework="4.6.1" executionTimeout="240" maxRequestLength="2048000" />
    <trace enabled="true" requestLimit="40" localOnly="false" />
  </system.web>
  <system.webServer>
    <defaultDocument>
      <files>
        <clear />
        <add value="Index.aspx" />
        <add value="Default.htm" />
        <add value="Default.asp" />
        <add value="index.htm" />
        <add value="index.html" />
        <add value="iisstart.htm" />
        <add value="default.aspx" />
      </files>
    </defaultDocument>
    <directoryBrowse enabled="false" />
  </system.webServer>
</configuration>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接