React Router에서 빌드 된 중첩 URL을 사용하는 하위 디렉토리에있는 SPA React 앱에서 Apache를 올바르게 구성하는 방법은 무엇입니까?

Jul 04 2020

내 웹 사이트가 하위 디렉토리 (예 : http : // mywebsite / admin)에 호스팅되어 있습니다. 여기서 / admin은 하위 디렉토리입니다.

내 반응 앱 (create-react-app 프로덕션 빌드)을 / admin 하위 디렉토리에 업로드했습니다. 또한 react-router v4 BrowserRouter를 사용하여 간단한 클라이언트 측 라우팅을 수행하고 있습니다. 다음은 내 반응 앱의 관련 스 니펫입니다.

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.

주요 문제 :/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]

그러면 모든 요청이 create-react-app 프로덕션 빌드로 빌드 된 index.html로 라우팅됩니다. 그러나 내 조사에서 이러한 유형의 구성은 하위 디렉토리에 있지 않고 중첩 된 URL을 사용하지 않는 프로젝트에서만 작동합니다.

.htaccess이제 2 개가 있습니다. 하나는 루트에 있고 다른 하나는 /admin하위 디렉토리에 있습니다. 둘 다 동일한 .htaccess코드를 포함합니다 . 그 이유는 루트 디렉터리에서 다른 SPA를 실행하고 있기 때문입니다.

내가 무엇을 놓치고 있습니까?

React Router에서 빌드 된 중첩 URL을 사용하는 하위 디렉토리에있는 SPA React 앱에서 Apache를 올바르게 구성하는 방법은 무엇입니까?

답변

2 MrWhite Jul 17 2020 at 00:05

주로 OP의 답변 및 기타 메모를 처리합니다.

이것은 내가 실수 한 곳입니다.

이제 2 개의 .htaccess가 있습니다. 하나는 루트에 있고 다른 하나는 / admin 하위 디렉토리에 있습니다. 둘 다 동일한 .htaccess 코드를 포함합니다. 그 이유는 루트 디렉터리에서 다른 SPA를 실행하고 있기 때문입니다.

이것은 반드시 "실수"가 아니 었습니다. 올바른 지시문을 사용하고 있는지 확인하기 만하면됩니다. 실제로 두 .htaccess파일을 완전히 별개의 SPA로 만들려는 경우 두 파일을 별도로 유지하는 것이 좋습니다.

두 개의 별개의 동일한 .htaccess파일을 가지려면 중요한 사항은 다음과 같습니다.

  • 대체 문자열을 상대적으로 만듭니다 . 슬래시 접두사가 없습니다.
  • RewriteBase지시문을 포함하지 마십시오 . (디렉터리 접두사를 재정의합니다.)

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의 솔루션과 약간 다른 점 admin/은 URL 경로 의 일부가 pathURL 매개 변수로 전달되지 않는다는 것 입니다. 필요한 경우이를 하드 코딩 할 수 있습니다. 예. index.html?path=admin/$1. 또는 스크립트에서 이것을 설명하십시오.

첫 번째 RewriteRule는 요청이 이미에 다시 작성된 후 추가 파일 시스템 검사를 방지하는 사소한 최적화입니다 index.html.

I가 변경된 것을 참고 (.*)(0 개 이상) (.+)(1 이상). 이렇게하면 루트 디렉터리를 요청할 때 추가 디렉터리 확인을 피할 수 있습니다. 즉. example.com/example.com/admin/. 이러한 요청을 다시 작성하지 않고 대신 DirectoryIndex index.html적절하게 설정 하는 데 의존 합니다. 이것은 서버 구성의 기본 설정입니다.

대체 문자열 ( index.php?page=$1)은 상대적 이기 때문에 문서 루트에 /index.php있을 때 효과적으로 다시 쓰게 되고 언제 /admin/.htaccess다시 /admin/index.php.

mod_rewrite 지시문은 기본적으로 상속되지 않으므로 (다른 모듈과 달리)의 mod_rewrite 지시문은 /admin/.htaccess상위 .htaccess파일 의 mod_rewrite 지시문을 완전히 재정의합니다 .


또는 반복을 피하기 위해 두 개의 개별 .htaccess파일을 유지하면서 파일에서 mod_rewrite 상속을 활성화 할 수 /admin/.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가 루트 .htaccess파일 에 종속되는 것 외에도 루트 파일에 중단 지시문을 추가하지 않도록주의해야 .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-path에서 "admin"을 검사하는 첫 번째 조건 (부수적으로 URL-path의 모든 위치 에서 "admin"을 검사합니다 ( 엄격히 정확하지 않음))은 필요하지 않습니다. 검사는 다음에서보다 최적으로 수행 될 수 있습니다. RewriteRule지시자 자체. 예를 들면 :

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 eric Jul 14 2020 at 06:35

이것은 내가 실수 한 곳입니다.

이제 2 개의 .htaccess가 있습니다. 하나는 루트에 있고 다른 하나는 / admin 하위 디렉토리에 있습니다. 둘 다 동일한 .htaccess 코드를 포함합니다. 그 이유는 루트 디렉터리에서 다른 SPA를 실행하고 있기 때문입니다.

간단하게 조정 내 루트 .htaccess 및 삭제.htaccess 내 질문에 설명 / 관리자 하위 디렉토리 고정 된 주요 문제 안에였습니다을.

루트 .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]
1 DanieleRicci Jul 09 2020 at 05:46

사실 문제에 대한 해답을 알고하지 않습니다,하지만 난 당신을 제안 할 수 있습니다 재생Location지침; 뭔가

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

도움이 되었기를 바랍니다.