React-Router-URLs funktionieren beim manuellen Aktualisieren oder Schreiben nicht

649

Ich verwende React-Router und es funktioniert gut, wenn ich auf Link-Schaltflächen klicke, aber wenn ich meine Webseite aktualisiere, wird nicht geladen, was ich will.

Zum Beispiel bin ich dabei localhost/joblistund alles ist in Ordnung, weil ich hier angekommen bin und einen Link gedrückt habe. Aber wenn ich die Webseite aktualisiere, bekomme ich:

Cannot GET /joblist

Standardmäßig hat es so nicht funktioniert. Anfangs hatte ich meine URL als localhost/#/und localhost/#/joblistund sie funktionierten einwandfrei. Aber ich mag diese Art von URL nicht, also habe #ich versucht, sie zu löschen :

Router.run(routes, Router.HistoryLocation, function (Handler) {
 React.render(<Handler/>, document.body);
});

Dieses Problem tritt nicht auf localhost/, dieses gibt immer zurück, was ich will.

BEARBEITEN: Diese App ist einseitig, /joblistmuss also keinen Server fragen.

EDIT2: Mein gesamter Router.

var routes = (
    <Route name="app" path="/" handler={App}>
        <Route name="joblist" path="/joblist" handler={JobList}/>
        <DefaultRoute handler={Dashboard}/>
        <NotFoundRoute handler={NotFound}/>
    </Route>
);

Router.run(routes, Router.HistoryLocation, function (Handler) {
  React.render(<Handler/>, document.body);
});
DavidDev
quelle
es sei denn, Sie verwenden htaccess, um Ihre Haupt-Touring-Seite zu laden und Ihren Router anzuweisen, location.pathname zu verwenden. Es wird nicht funktionieren.
Charles John Thompson III
Wie haben Sie dieses #Symbol gelöscht ? Vielen Dank!
SudoPlz
4
Wenn Sie Ihre Reaktions-App in einem S3-Bucket hosten, können Sie das Fehlerdokument einfach auf einstellen index.html. Dies stellt sicher, dass index.htmlgetroffen wird, egal was passiert.
Trevor Hutto
In meinem Fall funktioniert es gut in Windows, aber nicht unter Linux
Ejaz Karim
Dies ist die Referenz, die zur Lösung meines Problems beigetragen hat: github.com/facebook/create-react-app/blob/master/packages/…
jimbotron

Antworten:

1090

Angesichts der Kommentare zur akzeptierten Antwort und des allgemeinen Charakters dieser Frage („funktioniert nicht“) dachte ich, dass dies ein guter Ort für einige allgemeine Erklärungen zu den hier behandelten Themen sein könnte. Diese Antwort ist also als Hintergrundinformation / Ausarbeitung des spezifischen Anwendungsfalls des OP gedacht. Bitte bei mir tragen.

Serverseitig gegen Clientseite

Das Erste, was man darüber verstehen sollte, ist, dass es jetzt zwei Stellen gibt, an denen die URL interpretiert wird, während es früher nur eine gab. In der Vergangenheit, als das Leben einfach war, hat ein Benutzer eine Anfrage http://example.com/aboutan den Server gesendet, der den Pfadteil der URL überprüft, festgestellt hat, dass der Benutzer die Info-Seite angefordert hat, und diese Seite dann zurückgesendet.

Beim clientseitigen Routing, das React-Router bietet, sind die Dinge weniger einfach. Zunächst ist auf dem Client noch kein JS-Code geladen. Die allererste Anfrage wird also immer an den Server gerichtet. Daraufhin wird eine Seite zurückgegeben, die die zum Laden von React und React Router usw. erforderlichen Skript-Tags enthält. Erst wenn diese Skripte geladen wurden, wird Phase 2 gestartet. Wenn der Benutzer in Phase 2 beispielsweise auf den Navigationslink "Über uns" klickt, wird die URL nur lokal in http://example.com/about(ermöglicht durch die Verlaufs-API ) geändert , es wird jedoch keine Anforderung an den Server gestellt. Stattdessen erledigt React Router seine Aufgabe auf der Clientseite, bestimmt, welche React-Ansicht gerendert werden soll, und rendert sie. Angenommen, Ihre About-Seite muss keine REST-Aufrufe ausführen, ist dies bereits geschehen. Sie sind von "Home" zu "Über uns" gewechselt, ohne dass eine Serveranforderung ausgelöst wurde.

Wenn Sie also auf einen Link klicken, wird Javascript ausgeführt, das die URL in der Adressleiste manipuliert, ohne eine Seitenaktualisierung zu verursachen , was wiederum dazu führt, dass React Router einen Seitenübergang auf der Clientseite durchführt .

Überlegen Sie nun, was passiert, wenn Sie die URL kopieren, in die Adressleiste einfügen und per E-Mail an einen Freund senden. Ihr Freund hat Ihre Website noch nicht geladen. Mit anderen Worten, sie befindet sich noch in Phase 1 . Auf ihrem Computer läuft noch kein React Router. Ihr Browser wird also eine Serveranfrage an stellen http://example.com/about.

Und hier beginnt Ihr Ärger. Bis jetzt konnten Sie nur einen statischen HTML-Code auf der Webroot Ihres Servers platzieren. Dies würde jedoch zu 404Fehlern für alle anderen URLs führen, wenn dies vom Server angefordert wird . Dieselben URLs funktionieren auf der Clientseite einwandfrei , da dort React Router das Routing für Sie ausführt. Auf der Serverseite schlagen sie jedoch fehl, es sei denn, Sie lassen Ihren Server sie verstehen.

Kombination von server- und clientseitigem Routing

Wenn die http://example.com/aboutURL sowohl auf der Server- als auch auf der Clientseite funktionieren soll, müssen Sie Routen sowohl auf der Server- als auch auf der Clientseite einrichten. Macht Sinn, oder?

Und hier beginnen Ihre Entscheidungen. Die Lösungen reichen von der Umgehung des Problems über eine Catch-All-Route, die den Bootstrap-HTML-Code zurückgibt, bis hin zum isomorphen Ansatz, bei dem sowohl der Server als auch der Client denselben JS-Code ausführen.

.

Das Problem insgesamt umgehen: Hash-Verlauf

Mit Hash-Verlauf anstelle von Browser-Verlauf sieht Ihre URL für die About-Seite ungefähr so ​​aus: http://example.com/#/about Der Teil nach dem #Symbol hash ( ) wird nicht an den Server gesendet. Der Server sieht http://example.com/und sendet die Indexseite also nur wie erwartet. React-Router nimmt das #/aboutTeil auf und zeigt die richtige Seite an.

Nachteile :

  • "hässliche" URLs
  • Serverseitiges Rendern ist mit diesem Ansatz nicht möglich. In Bezug auf die Suchmaschinenoptimierung (SEO) besteht Ihre Website aus einer einzelnen Seite, auf der sich kaum Inhalte befinden.

.

Allheilmittel

Mit diesem Ansatz haben Sie verwenden Browser - Historie, aber nur eine allumfassende auf dem Server einrichten, sendet /*an index.html, effektiv Sie viel die gleiche Situation wie mit Hash Geschichte zu geben. Sie haben jedoch saubere URLs und können dieses Schema später verbessern, ohne alle Favoriten Ihres Benutzers ungültig machen zu müssen.

Nachteile :

  • Komplexer einzurichten
  • Immer noch keine gute SEO

.

Hybrid

Beim hybriden Ansatz erweitern Sie das Catch-All-Szenario, indem Sie bestimmte Skripte für bestimmte Routen hinzufügen. Sie können einige einfache PHP-Skripte erstellen, um die wichtigsten Seiten Ihrer Website mit eingeschlossenem Inhalt zurückzugeben, damit Googlebot zumindest sehen kann, was sich auf Ihrer Seite befindet.

Nachteile :

  • Noch komplexer einzurichten
  • Nur gute SEO für diese Routen geben Sie die Sonderbehandlung
  • Duplizieren von Code zum Rendern von Inhalten auf Server und Client

.

Isomorph

Was ist, wenn wir Node JS als Server verwenden, damit wir an beiden Enden denselben JS-Code ausführen können ? Jetzt haben wir alle unsere Routen in einer einzigen React-Router-Konfiguration definiert und müssen unseren Rendering-Code nicht mehr duplizieren. Dies ist sozusagen 'der heilige Gral'. Der Server sendet genau das gleiche Markup, das wir erhalten würden, wenn der Seitenübergang auf dem Client stattgefunden hätte. Diese Lösung ist in Bezug auf SEO optimal.

Nachteile :

  • Der Server muss JS ausführen können (können). Ich habe mit Java icw Nashorn experimentiert, aber es funktioniert nicht für mich. In der Praxis bedeutet dies meistens, dass Sie einen Node JS-basierten Server verwenden müssen.
  • Viele knifflige Umweltprobleme (Verwendung windowauf der Serverseite usw.)
  • Steile Lernkurve

.

Welches soll ich verwenden?

Wählen Sie die aus, mit der Sie durchkommen können. Persönlich denke ich, dass das Allheilmittel einfach genug ist, um es einzurichten, also wäre das mein Minimum. Mit diesem Setup können Sie die Dinge im Laufe der Zeit verbessern. Wenn Sie Node JS bereits als Serverplattform verwenden, würde ich auf jeden Fall eine isomorphe App untersuchen. Ja, es ist zunächst schwierig, aber sobald Sie den Dreh raus haben, ist es tatsächlich eine sehr elegante Lösung für das Problem.

Für mich wäre das also der entscheidende Faktor. Wenn mein Server auf Node JS läuft, würde ich isomorph werden. Andernfalls würde ich mich für die Catch-All-Lösung entscheiden und sie im Laufe der Zeit erweitern und die SEO-Anforderungen erfordern.

Wenn Sie mehr über isomorphes (auch als "universell" bezeichnetes) Rendering mit React erfahren möchten, gibt es einige gute Tutorials zu diesem Thema:

Um Ihnen den Einstieg zu erleichtern, empfehle ich Ihnen, sich einige Starter-Kits anzusehen. Wählen Sie eine aus, die Ihren Auswahlmöglichkeiten für den Technologie-Stack entspricht (denken Sie daran, React ist nur das V in MVC, Sie benötigen mehr Material, um eine vollständige App zu erstellen). Schauen Sie sich zunächst die von Facebook selbst veröffentlichte an:

Oder wählen Sie eine der vielen von der Community. Es gibt jetzt eine schöne Seite, die versucht, alle zu indizieren:

Ich habe mit diesen angefangen:

Derzeit verwende ich eine selbstgebraute Version des universellen Renderings, die von den beiden oben genannten Starter-Kits inspiriert wurde, aber jetzt veraltet ist.

Viel Glück bei deiner Suche!

Stijn de Witt
quelle
2
Toller Beitrag Stijn! Würden Sie empfehlen, ein Starter-Kit für eine isomorphe Reaktions-App zu verwenden? Wenn ja, könnten Sie ein Beispiel geben, das Sie bevorzugen würden?
Chris
1
@ Paulos3000 Es hängt davon ab, welchen Server Sie verwenden. Grundsätzlich definieren Sie eine Route für /*und lassen sie mit Ihrer HTML-Seite antworten. Das Schwierige dabei ist, sicherzustellen, dass Sie mit dieser Route keine Anforderungen für die .js- und .css-Dateien abfangen.
Stijn de Witt
2
@ Paulos3000 Hier finden Sie einige verwandte Fragen: für Apache / PHP , für Express / JS , für J2E / Java .
Stijn de Witt
1
Hallo, ich versuche die Hash-Lösung, aber kein Glück. Erste createMemoryHistory is not a functionFehler. Stört es dich? stackoverflow.com/questions/45002573/…
Leon Gaban
5
@LeonGaban Da diese Antwort geschrieben wurde, hat React Router anscheinend ihre Implementierung geändert. Sie haben jetzt verschiedene Router-Instanzen für die verschiedenen Historien und konfigurieren die Historie im Hintergrund. Die Grundprinzipien sind immer noch dieselben.
Stijn de Witt
115

Die Antworten hier sind alle äußerst hilfreich. Für mich hat es funktioniert, meinen Webpack-Server so zu konfigurieren, dass er die Routen erwartet.

devServer: {
   historyApiFallback: true,
   contentBase: './',
   hot: true
},

Der historyApiFallback hat dieses Problem für mich behoben. Jetzt funktioniert das Routing korrekt und ich kann die Seite aktualisieren oder die URL direkt eingeben. Sie müssen sich keine Gedanken über Problemumgehungen auf Ihrem Knotenserver machen. Diese Antwort funktioniert natürlich nur, wenn Sie Webpack verwenden.

BEARBEITEN: Siehe meine Antwort hier für einen detaillierteren Grund, warum dies notwendig ist: https://stackoverflow.com/a/37622953/5217568

jmancherje
quelle
16
Zu beachten ist, dass das Webpack Team empfiehlt gegen den Dev - Server in der Produktion.
Stijn de Witt
5
Für generische Entwicklungszwecke ist dies die beste Lösung. historyApiFallbackist ausreichend. Wie bei allen anderen Optionen kann sie auch über die CLI mit dem Flag festgelegt werden --history-api-fallback.
Marco Lazzeri
2
@ Kunok tut es nicht. Dies ist eine schnelle Lösung für die Entwicklung, aber Sie müssen noch etwas für die Produktion herausfinden.
Stijn de Witt
contentBase: ': /' weil auf Ihre App-Dateien über die URL zugegriffen werden kann
Nezih
85

Sie können Ihre .htaccessDatei ändern und Folgendes einfügen:

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-l
  RewriteRule . /index.html [L]
</IfModule>

Ich verwende react: "^16.12.0"und react-router: "^5.1.2" Diese Methode ist das Allheilmittel und wahrscheinlich der einfachste Weg, um Ihnen den Einstieg zu erleichtern.

BrahimS
quelle
3
Das funktioniert gut! und am einfachsten, wenn Sie Ihre App nicht umstrukturieren möchten
Mhyassin
7
Vergessen Sie nicht RewriteEngine On als erste Zeile
Kai Qing
2
Beachten Sie, dass sich diese Antwort auf die Konfiguration auf einem Apache-Server bezieht. Dies ist nicht Teil einer React-App.
Colton Hicks
Ich habe die obigen Antworten nicht verstanden. Keines der Tutorials sagte, dass meine Links überhaupt nicht live funktionieren würden. Diese einfache htaccess-Datei funktionierte jedoch. Danke
Thomas Williams
Dies funktioniert auch für den statischen Export von next.js. Da der Tomcat dem Knoten nicht ähnlich ist, benötigen wir diese zusätzliche Konfiguration für den statischen Export von next.js.
giri-jeedigunta
62

Für Benutzer von React Router V4 :

Wenn Sie versuchen, dieses Problem mithilfe der in anderen Antworten erwähnten Hash-Verlaufstechnik zu lösen, beachten Sie dies

<Router history={hashHistory} >

funktioniert nicht in V4, bitte verwenden Sie HashRouterstattdessen:

import { HashRouter } from 'react-router-dom'

<HashRouter>
  <App/>
</HashRouter>

Referenz: HashRouter

user2875289
quelle
29

Der Router kann auf zwei verschiedene Arten aufgerufen werden, je nachdem, ob die Navigation auf dem Client oder auf dem Server erfolgt. Sie haben es für den clientseitigen Betrieb konfiguriert. Der Schlüsselparameter ist der zweite Parameter der Ausführungsmethode , der Speicherort.

Wenn Sie die React Router Link-Komponente verwenden, blockiert sie die Browsernavigation und ruft TransitionTo auf, um eine clientseitige Navigation durchzuführen. Sie verwenden HistoryLocation und verwenden daher die HTML5-Verlaufs-API, um die Illusion der Navigation durch Simulieren der neuen URL in der Adressleiste zu vervollständigen. Wenn Sie ältere Browser verwenden, funktioniert dies nicht. Sie müssten die HashLocation-Komponente verwenden.

Wenn Sie auf Aktualisieren klicken, umgehen Sie den gesamten React- und React Router-Code. Der Server erhält die Anfrage für /joblistund muss etwas zurückgeben. Auf dem Server müssen Sie den angeforderten Pfad an die runMethode übergeben, damit sie die richtige Ansicht wiedergibt. Sie können dieselbe Routenkarte verwenden, benötigen jedoch wahrscheinlich einen anderen Anruf Router.run. Wie Charles betont, können Sie dazu das Umschreiben von URLs verwenden. Eine andere Option besteht darin, einen node.js-Server zu verwenden, um alle Anforderungen zu verarbeiten und den Pfadwert als Standortargument zu übergeben.

In Express könnte es beispielsweise so aussehen:

var app = express();

app.get('*', function (req, res) { // This wildcard method handles all requests

    Router.run(routes, req.path, function (Handler, state) {
        var element = React.createElement(Handler);
        var html = React.renderToString(element);
        res.render('main', { content: html });
    });
});

Beachten Sie, dass der Anforderungspfad an übergeben wird run. Dazu benötigen Sie eine serverseitige Ansichts-Engine, an die Sie den gerenderten HTML-Code übergeben können. Es gibt eine Reihe weiterer Überlegungen zur Verwendung renderToStringund Ausführung von React auf dem Server. Sobald die Seite auf dem Server gerendert ist und Ihre App auf dem Client geladen wird, wird sie erneut gerendert und aktualisiert den serverseitig gerenderten HTML-Code nach Bedarf.

Todd
quelle
2
Entschuldigung Entschuldigung, können Sie bitte die nächste Aussage erklären: "Wenn Sie auf Aktualisieren klicken, umgehen Sie den gesamten Code von React und React Router." Warum passiert das?
VB_
Der React Router wird normalerweise verwendet, um verschiedene "Pfade" nur innerhalb des Browsers zu verarbeiten. Es gibt zwei typische Möglichkeiten, dies zu tun: den Hash-Pfad im älteren Stil und die neuere Verlaufs-API. Bei einer Browseraktualisierung wird eine Serveranforderung gestellt, die Ihren clientseitigen Reaktionsroutercode umgeht. Sie müssen den Pfad auf dem Server verarbeiten (jedoch nur, wenn Sie die Verlaufs-API verwenden). Sie können hierfür den React Router verwenden, müssen jedoch etwas Ähnliches wie oben beschrieben tun.
Todd
verstanden. Aber wie soll es sein, wenn sich der Server in einer Nicht-JS-Sprache befindet (sagen wir Java)?
VB_
2
Entschuldigung ... Sie meinen, dass Sie einen Express-Server benötigen, um eine Route zu rendern, die "nicht root" ist? Ich war zuerst erstaunt, dass die Definition des Isomorphismus den Datenabruf nicht in sein Konzept einbezog (die Dinge sind äußerst komplex, wenn Sie die Ansicht MIT Datenserver rendern möchten, obwohl dies ein offensichtlicher SEO-Bedarf wäre - und der Isomorphismus behauptet dies). Jetzt bin ich wie "WTF reagieren", ernsthaft ... Korrigieren Sie mich, wenn ich falsch liege. Benötigt Ember / Angular / Backbone eine Server-Sache, um eine Route zu rendern? Ich verstehe diese aufgeblähte Anforderung, Routen zu verwenden, wirklich nicht
Ben
1
Bedeutet dies, dass die Aktualisierung im React-Router nicht funktioniert, wenn meine React-Anwendung nicht isomorph ist?
Matt
28

Fügen Sie in Ihrer index.html headFolgendes hinzu:

<base href="/">
<!-- This must come before the css and javascripts -->

Verwenden Sie dann diesen Befehl, wenn Sie mit dem Webpack-Entwicklungsserver ausgeführt werden.

webpack-dev-server --mode development --hot --inline --content-base=dist --history-api-fallback

--history-api-fallback ist der wichtige Teil

Efe Ariaroo
quelle
Das hat super geklappt! Gibt es Links, um mehr darüber zu erfahren, wie Sie diese Lösung gefunden haben?
JustDan
1
Entschuldigung Bruder. Fand es durch die bewährte Technik von Versuch und Irrtum.
Efe Ariaroo
Es ist erwähnenswert, dass, wenn Sie eine Basis-HREF verwenden, die /dann HashRouternicht funktioniert (wenn Sie Hash-Routing verwenden)
Robbie Averill
Das <base href = "/"> -Tag hat es für mich getan. Danke dafür. Der Webpack-Entwicklungsserver versuchte immer wieder, das Bundle vom Pfad / <Bundle> abzurufen, und schlug fehl.
Malisbad
27

Ich habe gerade die Create-React-App verwendet, um eine Website zu erstellen, und das gleiche Problem wurde hier vorgestellt. Ich benutze BrowserRoutingaus dem react-router-domPaket. Ich laufe auf einem Nginx-Server und habe das Problem gelöst, indem ich Folgendes hinzugefügt habe/etc/nginx/yourconfig.conf

location / {
  if (!-e $request_filename){
    rewrite ^(.*)$ /index.html break;
  }
}

.htaccessDies entspricht dem Hinzufügen des Folgenden zu dem Fall, dass Sie Appache ausführen

Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

Dies scheint auch die vorgeschlagene Lösung von Facebook selbst und finden Sie hier

Hilfe bei der
quelle
1
Wow, so eine einfache Lösung für Nginx; funktioniert wie ein Zauber, als neuer Nginx-Benutzer. Einfach kopieren, einfügen und los geht's. +1 für die Verknüpfung mit der offiziellen fb-Dokumentation. Gut gemacht.
user3773048
Für die Aufzeichnung: Ich verwende eine AWS-Instanz mit Nginx und einer Angular App. Das funktioniert.
Diego Sarmiento
Du rettest mich. Ich habe versucht, mein Problem von gestern zu beheben. Ich habe ein paar Lösungen satt, aber ich bin gescheitert. Schließlich haben Sie mir geholfen, dieses Router-Problem zu lösen. Ah, vielen Dank Bruder
Sharifur Robin
Gibt es etwas anderes, das für "reagieren" benötigt wird: "^ 16.8.6", "reagieren-Router": "^ 5.0.1"? Ich habe diese Lösungen (sowohl Nginx als auch Apache) ausprobiert und sie funktionieren nicht.
Mark A. Tagliaferro
Da Facebook seine Dokumentation dazu nicht geändert hat, kann ich nur davon ausgehen, dass das Verfahren das gleiche ist. Ich habe es schon eine Weile nicht mehr versucht.
Aidin
17

Dies kann Ihr Problem lösen

Ich hatte auch das gleiche Problem in der ReactJS-Anwendung im Produktionsmodus. Hier ist die 2 Lösung für das Problem.

1.Ändern Sie den Routing-Verlauf in "hashHistory" anstelle von browserHistory anstelle von

<Router history={hashHistory} >
   <Route path="/home" component={Home} />
   <Route path="/aboutus" component={AboutUs} />
</Router>

Erstellen Sie nun die App mit dem Befehl

sudo npm run build

Legen Sie dann den Build-Ordner in Ihren var / www / -Ordner. Jetzt funktioniert die Anwendung einwandfrei, und in jeder URL wird ein # -Tag hinzugefügt. mögen

localhost / # / home localhost / # / aboutus

Lösung 2: Ohne # -Tag mit browserHistory,

Setzen Sie Ihren Verlauf = {browserHistory} in Ihrem Router. Erstellen Sie ihn jetzt mit sudo npm run build.

Sie müssen die "conf" -Datei erstellen, um die nicht gefundene 404-Seite zu lösen. Die conf-Datei sollte folgendermaßen aussehen.

Öffnen Sie Ihr Terminal und geben Sie die folgenden Befehle ein

cd / etc / apache2 / sites-available ls nano sample.conf Fügen Sie den folgenden Inhalt hinzu.

<VirtualHost *:80>
    ServerAdmin admin@0.0.0.0
    ServerName 0.0.0.0
    ServerAlias 0.0.0.0
    DocumentRoot /var/www/html/

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    <Directory "/var/www/html/">
            Options Indexes FollowSymLinks
            AllowOverride all
            Require all granted
    </Directory>
</VirtualHost>

Jetzt müssen Sie die Datei sample.conf mit dem folgenden Befehl aktivieren

cd /etc/apache2/sites-available
sudo a2ensite sample.conf

Anschließend werden Sie aufgefordert, den Apache-Server mithilfe des sudo-Dienstes apache2 neu zu laden oder neu zu starten

Öffnen Sie dann Ihren Ordner localhost / build und fügen Sie die .htaccess-Datei mit dem folgenden Inhalt hinzu.

   RewriteEngine On
   RewriteBase /
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteCond %{REQUEST_FILENAME} !-d
   RewriteCond %{REQUEST_FILENAME} !-l
   RewriteRule ^.*$ / [L,QSA]

Jetzt funktioniert die App normal.

Hinweis: Ändern Sie die IP-Adresse 0.0.0.0 in Ihre lokale IP-Adresse.

Wenn Sie diesbezüglich Zweifel haben, können Sie gerne einen Kommentar abgeben.

Ich hoffe es ist hilfreich für andere.

Venkatesh Somu
quelle
Funktioniert die erste Lösung für "react-router-dom": "^5.1.2"? Ich verwende<BrowserRouter>
151291
16

Wenn Sie eine Reaktions-App über AWS Static S3 Hosting & CloudFront hosten

Dieses Problem trat auf, als CloudFront mit einer 403 Access Denied-Nachricht antwortete, weil erwartet wurde, dass / some / other / path in meinem S3-Ordner vorhanden ist, dieser Pfad jedoch nur intern im React-Routing mit dem React-Router vorhanden ist.

Die Lösung bestand darin, eine Regel für Verteilungsfehlerseiten einzurichten. Gehen Sie zu den CloudFront-Einstellungen und wählen Sie Ihre Distribution aus. Gehen Sie als nächstes zur Registerkarte "Fehlerseiten". Klicken Sie auf "Benutzerdefinierte Fehlerantwort erstellen" und fügen Sie einen Eintrag für 403 hinzu, da dies der Fehlerstatuscode ist, den wir erhalten. Setzen Sie den Pfad der Antwortseite auf /index.html und den Statuscode auf 200. Das Endergebnis überrascht mich mit seiner Einfachheit. Die Indexseite wird bereitgestellt, die URL bleibt jedoch im Browser erhalten. Sobald die Reaktions-App geladen ist, erkennt sie den URL-Pfad und navigiert zur gewünschten Route.

Fehlerseiten 403 Regel

th3morg
quelle
1
Genau das brauchte ich. Vielen Dank.
Jonathan
Also .. alle Ihre URLs funktionieren, aber den Statuscode 403 zurückgeben? Es ist nicht richtig. Die erwarteten Statuscodes sollten im Bereich 2xx liegen.
Stijn de Witt
@StijndeWitt Ich bin nicht sicher, ob Sie richtig verstehen. CloudFront übernimmt alles - der Client sieht keine 403-Statuscodes. Das Umleiten erfolgt serverseitig, rendert die Indexseite, verwaltet die URL und liefert als Ergebnis die richtige Route.
th3morg
@ th3morg Ah ja ich sehe jetzt. Ich habe übersehen, dass Sie damit auch den Antwortstatuscode als 200 eingeben können. Im Grunde ordnen Sie also den Status 403 dem Status 200 zu ... Sieht gut aus ... außer dass Sie möglicherweise aus einem anderen Grund 403 erhalten Sie werden es deshalb nicht sehen können.
Stijn de Witt
1
danke dafür @ th3morg. Funktioniert dieses Setup auch für mehrstufige Pfade? Es funktioniert gut für mich, wenn ein Pfad auf Stammebene wie Domäne / Anmeldung, Domäne / Anmeldung, Domäne / <Dokumenten-ID> vorhanden ist, aber es funktioniert nicht für mehrstufige Pfade wie Domäne / Dokument / <Dokumenten-ID>.
Pargles
15

Der Webpack Dev Server verfügt über eine Option, um dies zu aktivieren. Öffnen package.jsonund hinzufügen --history-api-fallback. Diese Lösung hat bei mir funktioniert.

React-Router-Tutorial

srijishks
quelle
3
Es ist in Ordnung, webpack-dev-serveraber wie behebe ich das für den Produktions-Build?
Hussain
12

Wenn Sie Ihre Reaktions-App auf IIS hosten, fügen Sie einfach eine web.config-Datei hinzu, die Folgendes enthält:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
        <remove statusCode="404" subStatusCode="-1" />
        <error statusCode="404" path="/" responseMode="ExecuteURL" />
    </httpErrors>
  </system.webServer>
</configuration>

Dadurch wird der IIS-Server angewiesen, die Hauptseite anstelle des 404-Fehlers an den Client zurückzugeben, ohne dass der Hash-Verlauf verwendet werden muss.

Chtiwi Malek
quelle
Dank bro!!!! es ist Arbeit!
Thanh Bao
12

Fügen Sie dies hinzu zu webpack.config.js:

devServer: {
    historyApiFallback: true
}
suraj
quelle
Das ist großartig für Entwickler, hilft aber nicht bei Produktions-Builds.
KFunk
11

Produktionsstapel: Reagieren, Reagieren Router v4, BrowswerRouter, Express, Nginx

1) User BrowserRouter für hübsche URLs

// app.js

import { BrowserRouter as Router } from 'react-router-dom'

const App = () {
  render() {
    return (
        <Router>
           // your routes here
        </Router>
    )
  }
}

2) Fügen Sie index.html allen unbekannten Anforderungen hinzu, indem Sie verwenden /*

// server.js

app.get('/*', function(req, res) {   
  res.sendFile(path.join(__dirname, 'path/to/your/index.html'), function(err) {
    if (err) {
      res.status(500).send(err)
    }
  })
})

3) Webpack mit bündeln webpack -p

4) laufen nodemon server.jsodernode server.js

BEARBEITEN: Möglicherweise möchten Sie nginx dies im Serverblock behandeln lassen und Schritt 2 ignorieren:

location / {
    try_files $uri /index.html;
}
Isaac Pak
quelle
Weg von undefiniert bekommen
Goutham
@Goutham Fügen Sie oben in Ihrer server.js-Datei entweder import path from 'pathoderconst path = require('path')
Isaac Pak
Schritt 2 (alles fangen mit /*) hat gerade meinen Tag gerettet. Vielen Dank! :)
Atlas7
Dies funktioniert, für Personen, die Redux verwenden und sich mit einem verbundenen Router befassen, siehe dieses Beispiel: github.com/supasate/connected-react-router/tree/master/examples/…
cjjenkinson
10

Wenn Sie die Create React App verwenden:

Es gibt jedoch einen guten Überblick über dieses Problem mit Lösungen für viele wichtige Hosting-Plattformen, die Sie HIER auf der Seite "React App erstellen" finden . Zum Beispiel verwende ich React Router v4 und Netlify für meinen Frontend-Code. Alles, was es brauchte, war 1 Datei zu meinem öffentlichen Ordner ("_redirects") und eine Codezeile in dieser Datei hinzuzufügen:

/*  /index.html  200

Jetzt rendert meine Website Pfade wie mysite.com/pricing ordnungsgemäß, wenn sie in den Browser eingegeben wird oder wenn jemand auf Aktualisieren klickt.

Colton Hicks
quelle
7

Versuchen Sie, die Datei ".htaccess" mit dem folgenden Code im öffentlichen Ordner hinzuzufügen.

RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]

RewriteRule ^ /index.html [L]  
Kiran Joshi
quelle
Danke, das hat bei Fedora 28 mit Apache für mich funktioniert. Keine der oben genannten Regeln zum Umschreiben oder die auf der CRA-Seite funktionierten für mich. Ich habe sie dem virtuellen Host-Setup hinzugefügt und nicht in einer separaten .htaccess-Datei.
Boerre
6

Wenn Sie einen Fallback auf Ihre index.html haben, stellen Sie sicher, dass Sie in Ihrer index.html-Datei Folgendes haben:

<script>
  System.config({ baseURL: '/' });
</script>

Dies kann von Projekt zu Projekt unterschiedlich sein.

Matt Goo
quelle
2
Fügen Sie dies Ihrem HTML hinzu head: <base href = "/">
Efe Ariaroo
4

Wenn Sie firebase verwenden, müssen Sie lediglich sicherstellen, dass Ihre Datei firebase.json im Stammverzeichnis Ihrer App (im Hosting-Bereich) eine Eigenschaft zum Umschreiben enthält.

Zum Beispiel:

{ 
  "hosting": {
    "rewrites": [{
      "source":"**",
      "destination": "/index.html"
    }]    
  }
}

Ich hoffe, dies erspart jemand anderem einen Haufen Frustration und Zeitverschwendung.

Viel Spaß beim Codieren ...

Weiterführende Literatur zu diesem Thema:

https://firebase.google.com/docs/hosting/full-config#rewrites

Firebase-CLI: "Als einseitige App konfigurieren (alle URLs in /index.html umschreiben)"

Joshua Dyck
quelle
Sie sind eine Legende
Perniferous
4

Ich habe die Lösung für mein SPA mit React Router (Apache) gefunden. Fügen Sie einfach .htaccess hinzu

<IfModule mod_rewrite.c>

  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-l
  RewriteRule . /index.html [L]

</IfModule>

Quelle: https://gist.github.com/alexsasharegan/173878f9d67055bfef63449fa7136042

Sasha Ignashevich
quelle
3

Ich verwende noch kein serverseitiges Rendering, aber ich habe das gleiche Problem wie das OP, bei dem Link die meiste Zeit gut zu funktionieren schien, aber fehlgeschlagen ist, als ich einen Parameter hatte. Ich werde meine Lösung hier dokumentieren, um zu sehen, ob sie jemandem hilft.

Mein Haupt-JSX enthält Folgendes:

<Route onEnter={requireLogin} path="detail/:id" component={ModelDetail} />

Dies funktioniert gut für den ersten passenden Link, aber wenn sich die: id ändert <Link> Ausdrücken , die auf der Detailseite des Modells verschachtelt sind, ändert sich die URL in der Browserleiste, aber der Inhalt der Seite wurde anfangs nicht geändert, um das verknüpfte Modell widerzuspiegeln.

Das Problem war, dass ich das verwendet hatte props.params.id, um das Modell einzurichtencomponentDidMount . Die Komponente wird nur einmal montiert. Dies bedeutet, dass das erste Modell auf der Seite haftet und die nachfolgenden Links die Requisiten ändern, die Seite jedoch unverändert bleibt.

Das Setzen des Modells in den Komponentenstatus in componentDidMountund in componentWillReceiveProps(wo es auf den nächsten Requisiten basiert) löst das Problem und der Seiteninhalt ändert sich, um das gewünschte Modell widerzuspiegeln.

Paul Whipp
quelle
1
Es ist möglicherweise besser, den Komponentenkonstruktor (der auch Zugriff auf propsiso hat ) zu verwenden, componentDidMountwenn Sie jemals versuchen möchten, serverseitig zu rendern. Denn componentDidMountwird nur im Browser aufgerufen. Der Zweck besteht darin, Dinge mit dem DOM zu tun, z. B. Ereignis-Listener an bodyusw. anzuhängen, die Sie nicht ausführen können render.
Stijn de Witt
3

Dieses Thema ist etwas alt und gelöst, aber ich möchte Ihnen eine einfache, klare und bessere Lösung vorschlagen. Es funktioniert, wenn Sie einen Webserver verwenden.

Jeder Webserver kann den Benutzer im Fall von http 404 auf eine Fehlerseite umleiten. Um dieses Problem zu beheben, müssen Sie den Benutzer auf die Indexseite umleiten.

Wenn Sie einen Java-Basisserver (Tomcat oder einen Java-Anwendungsserver) verwenden, kann die Lösung wie folgt aussehen:

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!-- WELCOME FILE LIST -->
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

    <!-- ERROR PAGES DEFINITION -->
    <error-page>
        <error-code>404</error-code>
        <location>/index.jsp</location>
    </error-page>

</web-app>

Beispiel:

  • GET http://example.com/about
  • Der Webserver löst http 404 aus, da diese Seite auf der Serverseite nicht vorhanden ist
  • Die Konfiguration der Fehlerseite teilt dem Server mit, der die Seite index.jsp an den Benutzer zurücksendet
  • dann erledigt JS den Rest der Arbeit auf der Clien-Seite, da die URL auf der Client-Seite immer noch http://example.com/about lautet .

Das ist es, keine Magie mehr nötig :)

Zappee
quelle
Das war großartig! Ich verwende den Wildfly 10.1-Server und habe dieses Update für meine Datei web.xml vorgenommen, außer dass für den Speicherort nur '/' festgelegt wurde. Dies lag daran, dass ich in meinem Reaktionscode den Browserverlauf wie folgt verwendet habe:const browserHistory = useRouterHistory(createHistory)({ basename: '/<appname>' });
Chuck L
1
Sind Sie sicher, dass dies keinen Einfluss auf SEO hat? Sie geben tatsächlich vorhandenen Seiten den Status 404. Der Benutzer wird dies vielleicht nie bemerken, aber Bots schenken viel Aufmerksamkeit, tatsächlich so viel, dass sie Ihre Seite nicht kratzen.
Subharb
3

Wenn Sie Express oder ein anderes Framework im Backend verwenden, können Sie die gleiche Konfiguration wie unten hinzufügen und den öffentlichen Webpack-Pfad in der Konfiguration überprüfen. Dies sollte auch beim Neuladen funktionieren, wenn Sie BrowserRouter verwenden

expressApp.get('/*', (request, response) => {
    response.sendFile(path.join(__dirname, '../public/index.html'));
});
user2849063
quelle
Dies ist die einfachste Lösung. Beachten Sie, dass diese Route nach allen anderen Routen verlaufen sollte, da es sich um einen Fang handelt
dcsan
3

Behebung des Fehlers "Kann nicht erhalten / URL" beim Aktualisieren oder beim direkten Aufrufen der URL.

Konfigurieren Sie Ihre webpack.config.js so , dass der angegebene Link die Routen wie folgt erwartet.

module.exports = {
  entry: './app/index.js',
  output: {
       path: path.join(__dirname, '/bundle'),
       filename: 'index_bundle.js',
       publicPath: '/'
  },
Lalit Tyagi
quelle
2

Bei der Verwendung von .Net Core MVC hat mir Folgendes geholfen:

    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            var url = Request.Path + Request.QueryString;
            return App(url);
        }

        [Route("App")]
        public IActionResult App(string url)
        {
            return View("/wwwroot/app/build/index.html");
        }
   }

Grundsätzlich fallen auf der MVC-Seite alle nicht übereinstimmenden Routen in die Home/Indexangegebenen Positionen startup.cs. Im Inneren ist Indexes möglich, die ursprüngliche Anforderungs-URL abzurufen und überall dort weiterzugeben, wo sie benötigt wird.

startup.cs

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");

            routes.MapSpaFallbackRoute(
                name: "spa-fallback",
                defaults: new { controller = "Home", action = "Index" });
        });
Elnoor
quelle
Wenn die Web-API von der App getrennt ist, wie werden Sie damit umgehen?
Dayanrr91
@ dayanrr91 Wenn Ihr Projekt über eine Web-API verfügt, benötigen Sie sowieso kein serverseitiges Routing. Und Ihr React-Router sollte meiner Meinung nach die URL lesen und das entsprechende Routing durchführen. Nichts sollte es blockieren
Elnoor
Ihr Kommentar wird sehr geschätzt, aber dann habe ich eine Frage, ich habe gerade HashRouter hinzugefügt, aber jetzt, wenn ich eine URL manuell eingebe, wird sie zu meiner Home-Komponente umgeleitet, anstatt zu meiner Home-Komponente und dann zu der Komponente, die ich versucht habe Steigen Sie ein, gibt es dafür eine Problemumgehung?
Dayanrr91
@ dayanrr91 keine Ahnung wirklich, habe noch nie Hashrouter ausprobiert, aber ich denke, sollte etwas mit Ihrem Code zu tun haben. Die Funktionsweise von Hashrouter sollte der von Browserrouter ähneln. Auch ich habe gerade hier in dieser Sandbox getestet, es funktioniert gut Codesandbox.io/s/25okp1mny , testen Sie die URL 25okp1mny.codesandbox.io/#/roster/5
Elnoor
2

Wenn Sie in IIS hosten; Das Hinzufügen zu meiner Webkonfiguration hat mein Problem gelöst

<httpErrors errorMode="Custom" defaultResponseMode="ExecuteURL">
    <remove statusCode="500" subStatusCode="100" />
    <remove statusCode="500" subStatusCode="-1" />
    <remove statusCode="404" subStatusCode="-1" />
    <error statusCode="404" path="/" responseMode="ExecuteURL" />
    <error statusCode="500" prefixLanguageFilePath="" path="/error_500.asp" responseMode="ExecuteURL" />
    <error statusCode="500" subStatusCode="100" path="/error_500.asp" responseMode="ExecuteURL" />
</httpErrors>

Sie können eine ähnliche Konfiguration für jeden anderen Server vornehmen

Scheune
quelle
1

Für den Fall, dass jemand hier nach einer Lösung für React JS SPA mit Laravel sucht. Die akzeptierte Antwort ist die beste Erklärung dafür, warum solche Probleme auftreten. Wie bereits erläutert, müssen Sie sowohl die Client- als auch die Serverseite konfigurieren. Fügen Sie in Ihre Blade-Vorlage die mitgelieferte js-Datei ein. Stellen Sie sicher, dass Sie URL facadediese verwenden

<script src="{{ URL::to('js/user/spa.js') }}"></script>

Stellen Sie in Ihren Routen sicher, dass dies dem Hauptendpunkt hinzugefügt wird, an dem sich die Blade-Vorlage befindet. Zum Beispiel,

Route::get('/setting-alerts', function () {
   return view('user.set-alerts');
});

Das Obige ist der Hauptendpunkt für die Blade-Vorlage. Fügen Sie jetzt auch eine optionale Route hinzu.

Route::get('/setting-alerts/{spa?}', function () {
  return view('user.set-alerts');
});

Das Problem besteht darin, dass zuerst die Blade-Vorlage und dann der Reaktionsrouter geladen wird. Wenn Sie also laden '/setting-alerts', werden HTML und JS geladen. Beim Laden '/setting-alerts/about'wird es jedoch zuerst auf der Serverseite geladen . Da sich auf der Serverseite an diesem Speicherort nichts befindet, wird nicht gefunden zurückgegeben. Wenn Sie über diesen optionalen Router verfügen, wird dieselbe Seite geladen, und der Reaktionsrouter wird ebenfalls geladen. Anschließend entscheidet der Reaktionslader, welche Komponente angezeigt werden soll. Hoffe das hilft.

Koushik Das
quelle
Ist es möglich, auf einen genauen URI auf den Server zu laden, dann leitet der Server eine Umleitung zu React durch? /user/{userID}Zum Beispiel muss ich beim Laden nur eine universelle /userHTML-Ansicht zurückgeben, die ID mitbringen und sie mit AJAX oder Axios aufrufen. Ist das möglich? Sind sie SEO-freundlich?
Ryuujo
1

Für diejenigen, die IIS 10 verwenden, sollten Sie dies tun, um dies zu korrigieren. Stellen Sie sicher, dass Sie browserHistory verwenden. Als Referenz werde ich den Code für das Routing angeben, aber das ist nicht wichtig, was wichtig ist, ist der nächste Schritt nach dem folgenden Komponentencode:

class App extends Component {
    render() {
        return (
            <Router history={browserHistory}>
                <div>
                    <Root>
                        <Switch>
                            <Route exact path={"/"} component={Home} />    
                            <Route path={"/home"} component={Home} />
                            <Route path={"/createnewproject"} component={CreateNewProject} />
                            <Route path={"/projects"} component={Projects} />
                            <Route path="*" component={NotFoundRoute} />
                        </Switch>
                    </Root>
                </div>
            </Router>
        )
    }
}
render (<App />, window.document.getElementById("app"));

Da das Problem darin besteht, dass IIS eine Anforderung von Client-Browsern empfängt, interpretiert es die URL so, als würde es nach einer Seite fragen, und gibt dann eine 404-Seite zurück, da keine Seite verfügbar ist. Mach Folgendes:

  1. Öffnen Sie IIS
  2. Erweitern Sie Server und öffnen Sie den Ordner Sites
  3. Klicken Sie auf die Website / Anwendung
  4. Gehen Sie zu den Fehlerseiten
  5. Öffnen Sie das 404-Fehlerstatuselement in der Liste
  6. Ändern Sie anstelle der Option "Inhalt aus statischer Datei in die Fehlerantwort einfügen" in "URL auf dieser Site ausführen" und fügen Sie der URL einen Schrägstrichwert "/" hinzu.

Und es wird jetzt gut funktionieren.

Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

Ich hoffe, es hilft. :-)

Martin Lloyd Jose
quelle
1

Ich verwende WebPack, ich hatte das gleiche Problem Lösung => In Ihrer server.js-Datei

const express = require('express');
const app = express();

app.use(express.static(path.resolve(__dirname, '../dist')));
  app.get('*', function (req, res) {
    res.sendFile(path.resolve(__dirname, '../dist/index.html'));
    // res.end();
  });

Warum wird meine Anwendung nach dem Aktualisieren nicht gerendert?

Vishal Singh
quelle
Das hat es für mich getan! Anfangs hatte ich res.sendFile (path.JOIN (publicPath, "index.html")); Ich habe "join" in "gelöst" geändert, wie im obigen Beispiel: res.sendFile (path.resolve ("./ dist", "index.html")); Ich habe auch mit __dirname herumgespielt, konnte es aber nicht wirklich verstehen oder zum Laufen bringen, also habe ich es manuell in "./dist" kopiert, da hier meine index.html bereitgestellt wird. Ich habe es auch so erklärt: app.use (express.static ("./ dist"));
Logixplayer
1

Verwenden Sie HashRouterfür mich auch mit Redux funktioniert , ersetzen Sie einfach:

import {
  Router //replace Router
} from "react-router-dom";

ReactDOM.render(
    <LocaleProvider locale={enUS}>
    <Provider store={Store}>
        <Router history={history}> //replace here saying Router
            <Layout/>
        </Router>
    </Provider>
</LocaleProvider>, document.getElementById("app"));
registerServiceWorker();

zu:

import {
  HashRouter //replaced with HashRouter
} from "react-router-dom";

ReactDOM.render(
    <LocaleProvider locale={enUS}>
    <Provider store={Store}>
        <HashRouter history={history}> //replaced with HashRouter
            <Layout/>
        </HashRouter>
    </Provider>
</LocaleProvider>, document.getElementById("app"));
registerServiceWorker();
Alireza
quelle
0

Ich hatte das gleiche Problem und das hier Lösung funktionierte für uns.

Hintergrund:

Wir hosten mehrere Apps auf demselben Server. Wenn wir aktualisieren würden, würde der Server nicht verstehen, wo er nach unserem Index im dist-Ordner für diese bestimmte App suchen soll. Der obige Link führt Sie zu dem, was für uns funktioniert hat ... Ich hoffe, dies hilft, da wir einige Stunden damit verbracht haben, eine Lösung für unsere Bedürfnisse zu finden.

Wir benutzen:

package.json

"dependencies": {
"babel-polyfill": "^6.23.0",
"ejs": "^2.5.6",
"express": "^4.15.2",
"prop-types": "^15.5.6",
"react": "^15.5.4",
"react-dom": "^15.5.4",
"react-redux": "^5.0.4",
"react-router": "^3.0.2",
"react-router-redux": "^4.0.8",
"redux": "^3.6.0",
"redux-persist": "^4.6.0",
"redux-thunk": "^2.2.0",
"webpack": "^2.4.1"
}

meine webpack.config.js

webpack.config.js

/* eslint-disable */
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const babelPolyfill = require('babel-polyfill');
const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
  template: __dirname + '/app/views/index.html',
  filename: 'index.html',
  inject: 'body'
});

module.exports = {
  entry: [
    'babel-polyfill', './app/index.js'
  ],
  output: {
    path: __dirname + '/dist/your_app_name_here',
    filename: 'index_bundle.js'
  },
  module: {
    rules: [{
      test: /\.js$/,
      loader: 'babel-loader',
      query : {
          presets : ["env", "react", "stage-1"]
      },
      exclude: /node_modules/
    }]
  },
  plugins: [HTMLWebpackPluginConfig]
}

meine index.js

index.js

import React from 'react'
import ReactDOM from 'react-dom'
import Routes from './Routes'
import { Provider } from 'react-redux'
import { createHistory } from 'history'
import { useRouterHistory } from 'react-router'
import configureStore from './store/configureStore'
import { syncHistoryWithStore } from 'react-router-redux'
import { persistStore } from 'redux-persist'

const store = configureStore();

const browserHistory = useRouterHistory(createHistory) ({
  basename: '/your_app_name_here'
})
const history = syncHistoryWithStore(browserHistory, store)

persistStore(store, {blacklist: ['routing']}, () => {
  console.log('rehydration complete')
})
// persistStore(store).purge()


ReactDOM.render(
    <Provider store={store}>
      <div>
        <Routes history={history} />
      </div>
    </Provider>,
  document.getElementById('mount')
)

meine app.js.

var express = require('express');
var app = express();

app.use(express.static(__dirname + '/dist'));
// app.use(express.static(__dirname + '/app/assets'));
app.set('views', __dirname + '/dist/your_app_name_here');
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');

app.get('/*', function (req, res) {
    res.render('index');
});

app.listen(8081, function () {
  console.log('MD listening on port 8081!');
});
J. Parrish
quelle
0

Ich mag diese Art, damit umzugehen. Versuchen Sie Folgendes hinzuzufügen: yourSPAPageRoute / * auf der Serverseite, um dieses Problem zu beheben.

Ich habe mich für diesen Ansatz entschieden, da selbst die native HTML5-Verlaufs-API die korrekte Umleitung bei der Seitenaktualisierung nicht unterstützt (soweit ich weiß).

Hinweis: Die ausgewählte Antwort hat dies bereits angesprochen, aber ich versuche, genauer zu sein.

Express Route

Test - Verlaufs-API Getestet und wollte dies nur teilen.

Ich hoffe es hilft.

Rehan
quelle