Wie konfiguriere ich Apache ordnungsgemäß in einer SPA-React-App, die sich in einem Unterverzeichnis befindet, das verschachtelte URLs verwendet, die aus React Router erstellt wurden?
Ich habe meine Website in einem Unterverzeichnis gehostet, beispielsweise http: // mywebsite / admin, wobei / admin das Unterverzeichnis ist
Ich habe meine React-App (Build-React-App-Produktions-Build) in das Unterverzeichnis / admin hochgeladen. Ich verwende auch den React-Router v4 BrowserRouter, um ein einfaches clientseitiges Routing durchführen zu lassen. Nachfolgend einige relevante Ausschnitte aus meiner 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"));
innerhalb der App.jsx-Renderfunktion
<Route
path='/students'
render={(props) =>
<Students
{...props}
/>
}
/>
<Route
path='/teachers'
render={(props) =>
<Teachers
{...props}
/>
}
/>
Alles ist gut und funktioniert beim Navigieren auf der Website, einschließlich der verschachtelten URLs, die hauptsächlich, wie Sie auf den Snippets gesehen haben, /admin/students
& /admin/teachers
.
Die wichtigste Frage: wenn ich auf der am /admin/teachers
Weg und ich die Seite aktualisieren , wird die Seite nicht alles geladen werden . Das Aktualisieren funktioniert nur, wenn ich /admin
unterwegs bin . Aber nicht wenn es /admin/teachers
noch ist /admin/students
.
Dies ist nicht das erste Mal, dass ich ein SPA mit dem auf dem Apache-Server gehosteten React-Router v4 erstellt habe. Ich habe den .htaccess, den ich für mein vorheriges Projekt habe, wiederverwendet. Dieser .htaccess befindet sich auch im /admin
Unterverzeichnis. Unten ist die .htaccess
:
.htaccess
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.html?path=$1 [NC,L,QSA]
Dadurch werden alle Anforderungen an die index.html weitergeleitet, die vom Produktionsbuild create-react-app erstellt wurde. Nach meinen Untersuchungen funktioniert diese Art der Konfiguration jedoch nur für ein Projekt, das sich nicht in einem Unterverzeichnis befindet und keine verschachtelten URLs verwendet.
Beachten Sie, dass ich jetzt 2 habe .htaccess
. Eine im Stammverzeichnis und eine im /admin
Unterverzeichnis. Beide enthalten die gleichen .htaccess
Codes . Der Grund dafür ist, dass im Stammverzeichnis ein anderes SPA ausgeführt wird.
Was vermisse ich?
Wie konfiguriere ich Apache ordnungsgemäß in einer SPA-React-App, die sich in einem Unterverzeichnis befindet, das verschachtelte URLs verwendet, die aus React Router erstellt wurden?
Antworten
In erster Linie die Antwort des OP sowie einige andere Hinweise ...
Hier habe ich einen Fehler gemacht:
Beachten Sie, dass ich jetzt 2 .htaccess habe. Eine im Stammverzeichnis und eine weitere im Unterverzeichnis / admin. Beide enthalten dieselben .htaccess-Codes. Der Grund dafür ist, dass im Stammverzeichnis ein anderes SPA ausgeführt wird.
Dies war nicht unbedingt ein "Fehler" - Sie müssten nur sicherstellen, dass Sie die richtigen Anweisungen verwenden. In der Tat .htaccess
könnte es vorzuziehen sein , die beiden Dateien getrennt zu halten, wenn es sich um vollständig getrennte SPAs handeln soll.
Um zwei separate - identische - .htaccess
Dateien zu haben, sind folgende wichtige Punkte:
- Machen Sie die Substitutionszeichenfolge relativ , dh. kein Schrägstrichpräfix.
- Fügen Sie keine
RewriteBase
Richtlinie hinzu. (Was das Verzeichnispräfix überschreiben würde.)
Wenn die RewriteRule
Ersetzungszeichenfolge ein relativer Pfad ist, wird das Verzeichnispräfix (dh der Speicherort der .htaccess
Datei) am Ende des Umschreibvorgangs wieder hinzugefügt.
Also beide /.htaccess
und /admin/.htaccess
würden identische Anweisungen enthalten:
RewriteEngine on
RewriteRule ^index\.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule (.+) index.html?path=$1 [L,QSA]
Ein kleiner Unterschied zu dieser Lösung und der OP-Lösung besteht jedoch darin, dass der admin/
Teil des URL-Pfads nicht an den path
URL-Parameter übergeben wird. Sie können dies bei Bedarf fest codieren. z.B. index.html?path=admin/$1
. Oder berücksichtigen Sie dies in Ihrem Skript.
Die erste RewriteRule
ist nur eine geringfügige Optimierung, die weitere Dateisystemprüfungen verhindert, nachdem die Anforderung bereits neu geschrieben wurde index.html
.
Beachten Sie, dass ich (.*)
(0 oder mehr) in (.+)
(1 oder mehr) geändert habe . Dies vermeidet die zusätzliche Verzeichnisprüfung beim Anfordern des Stammverzeichnisses. dh. example.com/
und example.com/admin/
. Sie schreiben diese Anforderungen nicht neu, sondern müssen DirectoryIndex index.html
sie entsprechend einstellen. Dies ist die Standardeinstellung in der Serverkonfiguration.
Da die Ersetzungszeichenfolge ( index.php?page=$1
) relativ ist, wird sie im Dokumentstamm effektiv umgeschrieben /index.php
und wenn /admin/.htaccess
sie sich im Dokumentstamm befindet, wird sie effektiv umgeschrieben /admin/index.php
.
Beachten Sie, dass die Anweisungen mod_rewrite die Anweisungen /admin/.htaccess
mod_rewrite in der übergeordneten .htaccess
Datei vollständig überschreiben, da die Anweisungen mod_rewrite (im Gegensatz zu anderen Modulen) nicht standardmäßig vererbt werden.
Um Wiederholungen zu vermeiden und gleichzeitig zwei separate .htaccess
Dateien zu verwalten, können Sie alternativ die Vererbung von mod_rewrite in der /admin/.htaccess
Datei aktivieren . Zum Beispiel...
In der Stammdatei /.htaccess
:
RewriteEngine on
RewriteRule ^index\.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule (.+) index.html?path=$1 [L,QSA]
Dann /admin/.htaccess
hätten Sie stattdessen folgendes:
RewriteEngine On
RewriteOptions Inherit
Diese erbt die übergeordneten mod_rewrite Richtlinien , als ob sie buchstäblich an Ort und Stelle in der kopierten /admin/.htaccess
Datei.
Dies fügt jedoch eine zusätzliche Komplexitätsebene hinzu. Abgesehen davon, dass das SPA /admin
jetzt von der Stammdatei abhängig ist .htaccess
, müssen Sie jetzt darauf achten, dass Sie der Stammdatei keine fehlerhaften Anweisungen hinzufügen .htaccess
.
Beiseite:
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]
Die erste Bedingung, die im URL-Pfad nach "admin" sucht (dies prüft übrigens irgendwo im URL-Pfad nach "admin" - was nicht unbedingt korrekt ist), ist nicht erforderlich - die Prüfung kann im Internet-Pfad optimaler durchgeführt werden RewriteRule
Richtlinie selbst. Zum Beispiel:
RewriteRule ^(admin/.*) admin/index.html?path=$1 [QSA,L]
Diese beiden Regeln können auf Wunsch zu einer zusammengefasst werden, möglicherweise auf Kosten einer gewissen Klarheit. Zum Beispiel:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(admin/)?.* $1index.html?path=$0 [QSA,L]
Die $1
Rückreferenz enthält dann entweder admin/
oder nichts das optionale Pfadpräfix . Und $0
enthält die vollständige Übereinstimmung.
Hier habe ich einen Fehler gemacht:
Beachten Sie, dass ich jetzt 2 .htaccess habe. Eine im Stammverzeichnis und eine weitere im Unterverzeichnis / admin. Beide enthalten dieselben .htaccess-Codes. Der Grund dafür ist, dass im Stammverzeichnis ein anderes SPA ausgeführt wird.
Durch einfaches Anpassen meines Stammverzeichnisses .htaccess
und Löschen des Stammverzeichnisses .htaccess
im Unterverzeichnis / admin wurde das in meiner Frage beschriebene Hauptproblem behoben.
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]
Ich kenne die Antwort auf Ihr Problem eigentlich nicht, aber ich kann Ihnen vorschlagen, mit der Direktive zu spielenLocation
. etwas wie
<Location "/admin">
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /admin/index.html?path=$1 [NC,L,QSA]
</Location>
Hoffe das hilft.