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?

Jul 04 2020

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/teachersWeg und ich die Seite aktualisieren , wird die Seite nicht alles geladen werden . Das Aktualisieren funktioniert nur, wenn ich /adminunterwegs bin . Aber nicht wenn es /admin/teachersnoch 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 /adminUnterverzeichnis. 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 /adminUnterverzeichnis. Beide enthalten die gleichen .htaccessCodes . 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

2 MrWhite Jul 17 2020 at 00:05

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 .htaccesskönnte es vorzuziehen sein , die beiden Dateien getrennt zu halten, wenn es sich um vollständig getrennte SPAs handeln soll.

Um zwei separate - identische - .htaccessDateien zu haben, sind folgende wichtige Punkte:

  • Machen Sie die Substitutionszeichenfolge relativ , dh. kein Schrägstrichpräfix.
  • Fügen Sie keine RewriteBaseRichtlinie hinzu. (Was das Verzeichnispräfix überschreiben würde.)

Wenn die RewriteRule Ersetzungszeichenfolge ein relativer Pfad ist, wird das Verzeichnispräfix (dh der Speicherort der .htaccessDatei) am Ende des Umschreibvorgangs wieder hinzugefügt.

Also beide /.htaccessund /admin/.htaccesswü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 pathURL-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 RewriteRuleist 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.htmlsie 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.phpund wenn /admin/.htaccesssie sich im Dokumentstamm befindet, wird sie effektiv umgeschrieben /admin/index.php.

Beachten Sie, dass die Anweisungen mod_rewrite die Anweisungen /admin/.htaccessmod_rewrite in der übergeordneten .htaccessDatei 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 .htaccessDateien zu verwalten, können Sie alternativ die Vererbung von mod_rewrite in der /admin/.htaccessDatei 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/.htaccesshä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/.htaccessDatei.

Dies fügt jedoch eine zusätzliche Komplexitätsebene hinzu. Abgesehen davon, dass das SPA /adminjetzt 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 RewriteRuleRichtlinie 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 $1Rückreferenz enthält dann entweder admin/oder nichts das optionale Pfadpräfix . Und $0enthält die vollständige Übereinstimmung.

2 eric Jul 14 2020 at 06:35

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

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.