Reactルーターから構築されたネストされたURLを使用するサブディレクトリにあるSPAReactアプリでApacheを適切に構成するにはどうすればよいですか?

Jul 04 2020

例として、http:// mywebsite / adminなどのサブディレクトリでWebサイトをホストしています。ここで/ adminはサブディレクトリです。

/ adminサブディレクトリにreactアプリ(create-react-appプロダクションビルド)をアップロードしています。また、react-router v4 BrowserRouterを使用して、いくつかの単純なクライアント側ルーティングを実行しています。以下は私の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

主な問題:/admin/teachersルート上でページ更新すると、ページに何も読み込まれません。リフレッシュは、/adminルート上でのみ機能します。しかし、そうでないときはそうではあり/admin/teachersません/admin/students

Apacheサーバーでホストされているreact-routerv4を使用して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つ持っていることに注意してください。1つはルートにあり、もう1つは/adminサブディレクトリにあります。どちらにも同じ.htaccessコードが含まれています。これは、ルートディレクトリで別のSPAを実行しているためです。

何が足りないのですか?

Reactルーターから構築されたネストされたURLを使用するサブディレクトリにあるSPAReactアプリでApacheを適切に構成するにはどうすればよいですか?

回答

2 MrWhite Jul 17 2020 at 00:05

主にOPの回答に加えて、その他の注意事項について説明します。

これは私が間違えたところです:

現在、2つの.htaccessがあることに注意してください。1つはルートにあり、もう1つは/ adminサブディレクトリにあります。どちらにも同じ.htaccessコードが含まれています。これは、ルートディレクトリで別のSPAを実行しているためです。

これは必ずしも「間違い」ではありませんでした。正しいディレクティブを使用していることを確認する必要があります。実際、.htaccessこれらが完全に別々のSPAであることが意図されている場合は、2つのファイルを別々に保つことが望ましい場合があります。

2つの別々の(同一の).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。または、スクリプトでこれを説明します。

1つ目RewriteRuleは、リクエストがに書き換えられた後のファイルシステムチェックを防ぐマイナーな最適化ですindex.html

(.*)(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ディレクティブを完全にオーバーライドすることに注意してください。


または、繰り返しを避けるために、2つの別々の.htaccessファイルを維持しながら、/admin/.htaccessファイルでmod_rewrite継承を有効にすることができます。例えば...

ルート/.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ます。

ただし、これにより複雑さが増します。SPAが/adminルート.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パスの「admin」をチェックする最初の条件(ちなみに、これはURLパスのどこかで「admin」をチェックします-厳密には正しくありません)は必要ありません-チェックはでより最適に実行できますRewriteRuleディレクティブ自体。例えば:

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

これらの2つのルールは、必要に応じて1つに組み合わせることができますが、ある程度の明確さが犠牲になる可能性があります。例えば:

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があることに注意してください。1つはルートにあり、もう1つは/ 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>

お役に立てれば。