我有我的网站托管在一个子目录,作为一个例子,超文本传输协议://mysite/admin,其中 /admin是子目录
我有我的反应应用程序(创建-反应-应用生产构建)上传到 /admin子目录。我也在使用react-router v4 Browser路由器来执行一些简单的客户端路由。下面是我的反应应用程序上的一些相关片段:
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
import { BrowserRouter } from 'react-router-dom';
import './css/custom.css';
ReactDOM.render(<BrowserRouter basename="/admin"><App /></BrowserRouter>, document.getElementById("root"));
内部应用程序。jsx渲染函数
<Route
path='/students'
render={(props) =>
<Students
{...props}
/>
}
/>
<Route
path='/teachers'
render={(props) =>
<Teachers
{...props}
/>
}
/>
当浏览网站时,包括嵌套的网址,这些网址主要是,正如你在代码片段中看到的,所有这些都是好的和工作的。
主要问题:当我在/admin/teachers
路线上时,我刷新页面,页面不会加载任何内容。仅当我在/admin
路线上时,刷新才起作用。但不是在/admin/teachers
或/admin/students
时。
这不是我第一次使用Apache服务器上托管的react-router v4构建SPA。我在以前的项目中重用了. htaccess。htaccess也位于/admin
子目录中。下面是. htaccess
:
。htaccess
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.html?path=$1 [NC,L,QSA]
这会将所有请求路由到索引。由CreateReact应用程序生产版本生成的html。但是,根据我的调查,这种类型的配置只适用于不在子目录中且不使用嵌套URL的项目。
注意,我有2个。htaccess
现在。一个在根目录下,另一个在/admin
子目录下 两者都包含相同的。htaccess
代码。原因是,我在根目录下运行了另一个SPA。
我错过了什么?
如何在SPA React应用程序上正确配置Apache,该应用程序位于使用React路由器构建的嵌套URL的子目录上?
主要针对OP的答案,再加上一些其他注释。。。
这就是我犯了一个错误的地方:
注意,我有2个。现在就进入。一个在根目录下,另一个在/admin子目录下。两者都包含相同的内容。HTC访问代码。原因是,我在根目录下运行了另一个SPA。
这不一定是一个“错误”——您只需要确保使用了正确的指令。事实上,保留这两个。htaccess
如果这些文件是完全独立的SPA,则最好是单独的文件。
有两个独立的相同的-。htaccess
文件要点包括:
当RewriteRule
替换字符串是相对路径时,目录前缀(即.htaccess
文件的位置)将添加回重写过程的末尾。
所以,两者都是/。htaccess
和/admin/。htaccess将包含相同的指令:
RewriteEngine on
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.+) index.html?path=$1 [L,QSA]
但是,与此解决方案和OP的解决方案稍有不同的是,URL路径的admin/
部分没有传递给path
URL参数。如果需要,您可以对其进行硬编码。例如,索引。html?path=admin/$1
。或者在脚本中说明这一点。
第一个RewriteRule
只是一个小小的优化,它可以防止在请求已被重写到索引后进行进一步的文件系统检查。html
。
请注意,我将(.*)
(0或更多)更改为(.)代码>(1个或多个)。这避免了在请求根目录时进行额外的目录检查。例如。com/
和示例。com/admin/
。您没有重写这些请求,而是依赖于DirectoryIndex。html
设置正确-这是服务器配置中的默认设置。
由于替换字符串(index.php?page=$1
)是相对的,因此在文档根目录中,它将有效地重写为/index。php
和在/admin/中时。htaccess
它将有效地重写回/admin/index。php
。
注意,/admin/中的mod_rewrite指令。htaccess
完全覆盖父级中的mod_rewrite指令。htaccess
文件,因为mod_重写指令在默认情况下不会继承(与其他模块不同)。
或者,为了避免重复,同时仍保持两个独立的。htaccess
文件您可以在/admin/中启用mod_rewrite继承。htaccess
文件。例如
在根目录中/。htaccess
文件:
RewriteEngine on
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.+) index.html?path=$1 [L,QSA]
然后,在/admin/。htaccess
您将拥有以下内容:
RewriteEngine On
RewriteOptions Inherit
这继承了父mod_rewrite指令,就好像它们是在/admin/中就地复制的一样。htaccess
文件。
然而,这增加了额外的复杂性。除了/admin
中的SPA现在依赖于root. htaccess
文件之外,您现在必须小心不要向root. htaccess
文件添加任何中断指令。
旁白:
RewriteCond %{REQUEST_URI} admin
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) admin/index.html?path=$1 [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.html?path=$1 [QSA,L]
检查URL路径中的admin的第一个条件(顺便说一下,这检查URL路径中的任何地方的admin-这不是严格正确的)是不需要的-检查可以在ReWriteLaw
指令本身中更优化地执行。例如:
RewriteRule ^(admin/.*) admin/index.html?path=$1 [QSA,L]
如果需要,这两个规则可以合并成一个,可能以牺牲一些清晰度为代价。例如:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(admin/)?.* $1index.html?path=$0 [QSA,L]
1美元
反向引用然后包含可选的路径前缀,要么是admin/
,要么什么都没有。并且0美元
包含完全匹配。
这就是我犯了一个错误的地方:
注意,我有2个。现在就进入。一个在根目录下,另一个在/admin子目录下。两者都包含相同的内容。HTC访问代码。原因是,我在根目录下运行了另一个SPA。
只需调整我的根。htaccess
并删除。htaccess
位于/admin子目录中,修复了我的问题中描述的主要问题。
root. htaccess:
RewriteCond %{REQUEST_URI} admin
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) admin/index.html?path=$1 [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.html?path=$1 [QSA,L]
我实际上不知道你问题的答案,但是我可以建议你玩位置
指令;类似这样的东西
<Location "/admin">
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /admin/index.html?path=$1 [NC,L,QSA]
</Location>
希望这有帮助。