如何在SPA React应用程序上正确配置Apache,该应用程序位于使用从React Router构建的嵌套URL的子目录中? [英] How to Properly Configure Apache on a SPA React App that Resides on a Subdirectory that uses Nested URLs built from React Router?

查看:82
本文介绍了如何在SPA React应用程序上正确配置Apache,该应用程序位于使用从React Router构建的嵌套URL的子目录中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的网站托管在一个子目录中,例如http://mywebsite/admin,其中/admin是子目录

我将我的react应用程序(create-react-app生产版本)上传到/admin子目录中.我还使用react-router v4 BrowserRouter来执行一些简单的客户端路由.以下是我的react-app上的一些相关片段:

index.js

I have my website hosted on a subdirectory, as an example, http://mywebsite/admin, where /admin is the subdirectory

I have my react app (create-react-app production build) uploaded into the /admin subdirectory. I am also using react-router v4 BrowserRouter to have some simple client-side routing performed. Below are some relevant snippets on my react-app:

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"));

App.jsx渲染功能内部

<Route
    path='/students'
    render={(props) =>
        <Students
            {...props}
        />
    }
/>

<Route
    path='/teachers'
    render={(props) =>
        <Teachers
            {...props}
        />
    }
/>

导航网站时,一切都很好,并且工作正常,包括嵌套的url,主要是您在代码段中看到的/admin/students /admin/teachers .

All is well and working when navigating the site including the nested urls which are mainly, as you have seen on the snippets, /admin/students & /admin/teachers.

主要问题:当我在/admin/teachers 路线上并且刷新页面时,该页面未加载任何内容.仅当我在/admin 路线上时,刷新功能有效.但是不是/admin/teachers /admin/students 时.

The main issue: when I am on the /admin/teachers route and I refresh the page, the page does not load anything. Refreshing works when I am on /admin route only. But not when it is /admin/teachers nor /admin/students.

这不是我第一次使用Apache服务器上托管的react-router v4构建SPA.我已经重用了先前项目中的.htaccess文件.该.htaccess也位于/admin 子目录中.以下是 .htaccess :

This is not the first time I have built an SPA using react-router v4 hosted on Apache server. I have reused the .htaccess I have on my previous project. This .htaccess also resides at the /admin subdirectory. Below is the .htaccess:

.htaccess

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.html?path=$1 [NC,L,QSA]

这会将所有请求路由到由create-react-app生产版本构建的index.html.但是,根据我的调查,这种类型的配置仅适用于不在子目录上且未使用嵌套URL的项目.

This routes all requests to the index.html built by the create-react-app production build. However, upon my investigations, this type of configuration only works on a project that is not on a subdirectory and is not using nested URLs.

请注意,我现在有2个 .htaccess .一个在根上,另一个在/admin 子目录中.两者都包含相同的 .htaccess 代码.原因是,我在根目录下还有另一个SPA.

Note, that I have 2 .htaccess now. One on root and another one at the /admin subdirectory. Both contain the same .htaccess codes. The reason for this is, I have another SPA running at the root directory.

我想念什么?

如何在SPA React应用程序上正确配置Apache,该应用程序位于使用从React Router构建的嵌套URL的子目录中?

How to Properly Configure Apache on a SPA React App that Resides on a Subdirectory that uses Nested URLs built from React Router?

推荐答案

从根本上解决 OP的答案笔记...

Primarily addressing the OP's answer, plus some other notes...

这是我犯错的地方:

This is where I made a mistake:

请注意,我现在有2个.htaccess.一个扎根,另一个扎根/admin子目录.两者都包含相同的.htaccess代码.原因为此,我在根目录下运行了另一个SPA.

Note, that I have 2 .htaccess now. One on root and another one at the /admin subdirectory. Both contain the same .htaccess codes. The reason for this is, I have another SPA running at the root directory.

这不一定是错误".-您只需要确保使用正确的指令即可.实际上,如果两个 .htaccess 文件打算完全是分开的SPA,则最好将它们分开.

This wasn't necessarily a "mistake" - you would just need to make sure you are using the correct directives. In fact, keeping the two .htaccess files separate could be preferable if these are intended to be entirely separate SPAs.

要拥有两个独立的-相同的 .htaccess 文件,重点是:

To have two separate - identical - .htaccess files the important points are:

  • 使替换字符串为 relative ,即.没有斜杠前缀.
  • 请勿包含 RewriteBase 指令.(这将覆盖目录前缀.)
  • Make the substitution string relative, ie. no slash prefix.
  • Do not include a RewriteBase directive. (Which would override the directory-prefix.)

RewriteRule substitution 字符串是 relative 路径时,则使用目录前缀(即 .htaccess的位置)文件)添加到重写过程的最后.

When the RewriteRule substitution string is a relative path then the directory-prefix (ie. the location of the .htaccess file) is added back at the end of the rewriting process.

因此,/.htaccess /admin/.htaccess 都将包含相同的指令:

So, both /.htaccess and /admin/.htaccess would contain identical directives:

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参数.如果需要,您可以对此进行硬编码.例如. index.html?path = admin/$ 1 .或在您的脚本中对此进行说明.

HOWEVER, a slight difference with this solution and the OP's solution is that the admin/ part of the URL-path is not passed to the path URL parameter. You could hardcode this if required. eg. index.html?path=admin/$1. Or account for this in your script.

第一个 RewriteRule 只是一个较小的优化,可防止在请求已被重写为 index.html 后进一步进行文件系统检查.

The first RewriteRule is just a minor optimisation that prevents further filesystem checks after the request has already been rewritten to index.html.

请注意,我将(.*)(0或更多)更改为(.+)(1或更多).这样可以避免在请求根目录时进行其他目录检查.IE. example.com/ example.com/admin/.您不是要重写这些请求,而是要依赖正确设置的 DirectoryIndex index.html -这是服务器配置中的默认设置.

Note that I changed (.*) (0 or more) to (.+) (1 or more). This avoids the additional directory check when requesting the root directory. ie. example.com/ and example.com/admin/. You are not rewriting these requests, but instead are reliant on DirectoryIndex index.html being set appropriately - this is the default setting in the server config.

由于 substitution 字符串( index.php?page = $ 1 )是相对的,因此在文档根目录中时,它将有效地重写为/index.php,并且在/admin/.htaccess 中使用时,它将有效地改写回/admin/index.php .

Since the substitution string (index.php?page=$1) is relative, when in the document root it will effectively rewrite to /index.php and when in /admin/.htaccess it will effectively rewrite back to /admin/index.php.

请注意,由于默认情况下不继承mod_rewrite指令,因此/admin/.htaccess 中的mod_rewrite指令完全覆盖了父 .htaccess 文件中的mod_rewrite指令.模块).

Note that the mod_rewrite directives in /admin/.htaccess completely override the mod_rewrite directives in the parent .htaccess file since mod_rewrite directives are not inherited by default (unlike other modules).

或者,为避免重复,同时仍保持两个单独的 .htaccess 文件,您可以在/admin/.htaccess 文件中启用mod_rewrite继承.例如...

Alternatively, to avoid repetition, whilst still maintaining two separate .htaccess files you could enable mod_rewrite inheritance in the /admin/.htaccess file. For example...

在根/.htaccess 文件中:

RewriteEngine on
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.+) index.html?path=$1 [L,QSA]

然后,在/admin/.htaccess 中,您将获得以下内容:

Then, in /admin/.htaccess you would have the following instead:

RewriteEngine On
RewriteOptions Inherit

继承父mod_rewrite指令,就好像它们是原地在/admin/.htaccess 文件中原地复制的一样.

This inherits the parent mod_rewrite directives as if they were literally copied in-place in the /admin/.htaccess file.

但是,这增加了一层额外的复杂性.除了/admin 中的SPA现在依赖于根 .htaccess 文件之外,您现在还必须注意不要添加任何 breaking .htaccess 文件的em>指令.

However, this adds an additional layer of complexity. Apart from the SPA in /admin now being dependent on the root .htaccess file, you now have to be careful that you don't add any breaking directives to the root .htaccess file.

旁边:

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路径中进行检查(顺便说一句,这并不严格检查URL路径中的"admin" -并非严格正确)-可以在 RewriteRule 指令本身.例如:

The first condition that checks for "admin" in the URL-path (incidentally, this checks for "admin" anywhere in the URL-path - which isn't strictly correct) is not required - the check can be performed more optimally in the RewriteRule directive itself. For example:

RewriteRule ^(admin/.*) admin/index.html?path=$1 [QSA,L]

如果需要的话,可以将这两个规则组合为一个规则,但这可能会牺牲一些清晰度.例如:

These two rules can be combined into one if desired, possibly at the expense of some clarity. For example:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(admin/)?.* $1index.html?path=$0 [QSA,L]

$ 1 后向引用包含可选的路径前缀,或者为 admin/ nothing .并且 $ 0 包含完整匹配项.

The $1 backreference then contains the optional path-prefix, either admin/ or nothing. And $0 contains the full match.

这篇关于如何在SPA React应用程序上正确配置Apache,该应用程序位于使用从React Router构建的嵌套URL的子目录中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆