如何为 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>
到<VirtualHost ...>
下的上述文件
【讨论】:
谢谢这个帮了我很多,节省了我的时间。 对于谷歌员工,<Directory "/var/www/html">
和 </Directory>
是使其正常工作所必需的。
在使用 .htaccess 文件之前,我们需要更新 AllowOverride
设置以便能够覆盖 Apache 指令。编辑文件/etc/httpd/conf/httpd.conf
找到<Directory /var/www/html>
部分并将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 文件通过<script>
导入或作为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