Ich verwende S3, um eine Javascript-App zu hosten, die HTML5-PushStates verwendet. Das Problem ist, wenn der Benutzer eine der URLs mit einem Lesezeichen versehen kann, wird keine Lösung gefunden. Was ich brauche, ist die Fähigkeit, alle URL-Anfragen entgegenzunehmen und die root index.html in meinem S3-Bucket bereitzustellen, anstatt nur eine vollständige Umleitung durchzuführen. Dann könnte meine Javascript-Anwendung die URL analysieren und die richtige Seite bereitstellen.
Gibt es eine Möglichkeit, S3 anzuweisen, die index.html für alle URL-Anforderungen bereitzustellen, anstatt Weiterleitungen durchzuführen? Dies ähnelt dem Einrichten von Apache zur Verarbeitung aller eingehenden Anforderungen durch Bereitstellen einer einzelnen index.html wie in diesem Beispiel: https://stackoverflow.com/a/10647521/1762614 . Ich möchte wirklich vermeiden, einen Webserver zu betreiben, nur um diese Routen zu handhaben. Alles von S3 aus zu tun ist sehr ansprechend.
Antworten:
Mit Hilfe von CloudFront ist es sehr einfach, es ohne URL-Hacks zu lösen.
quelle
Ich konnte dies wie folgt zum Laufen bringen:
Im bearbeiten Umleitungsregeln Abschnitt der S3 - Konsole für Ihre Domain, fügen Sie die folgenden Regeln:
Dadurch werden alle Pfade, die dazu führen, dass ein 404 nicht gefunden wird, mit einer Hash-Bang-Version des Pfads in Ihre Stammdomäne umgeleitet. Daher wird http://yourdomainname.com/posts zu http://yourdomainname.com/#!/posts umgeleitet, sofern keine Datei unter / posts vorhanden ist.
Um HTML5 pushStates zu verwenden, müssen wir diese Anforderung annehmen und manuell den richtigen pushState basierend auf dem Hash-Bang-Pfad einrichten. Fügen Sie dies also oben in Ihre index.html-Datei ein:
Dadurch wird der Hash erfasst und in einen HTML5-PushState umgewandelt. Ab diesem Zeitpunkt können Sie pushStates verwenden, um Nicht-Hash-Bang-Pfade in Ihrer App zu haben.
quelle
<script language="javascript"> if (typeof(window.history.pushState) == 'function') { window.history.pushState(null, "Site Name", window.location.hash.substring(2)); } else { window.location.hash = window.location.hash.substring(2); } </script>
react-router
mit dieser Lösung unter Verwendung von HTML5 pushStates und<ReplaceKeyPrefixWith>#/</ReplaceKeyPrefixWith>
Es gibt nur wenige Probleme mit dem von anderen erwähnten S3 / Redirect-basierten Ansatz.
Die Lösung ist:
Konfigurieren Sie Fehlerseitenregeln für Ihre Cloudfront-Instanz. Geben Sie in den Fehlerregeln Folgendes an:
HTTP-Antwortcode: 200
Konfigurieren Sie eine EC2-Instanz und richten Sie einen Nginx-Server ein.
Ich kann Ihnen bei weiteren Details zum Nginx-Setup helfen. Hinterlassen Sie einfach eine Notiz. Habe es auf die harte Tour gelernt.
Sobald die Cloud-Front-Distribution aktualisiert wurde. Machen Sie Ihren Cloudfront-Cache einmal ungültig, um sich im makellosen Modus zu befinden. Klicken Sie auf die URL im Browser und alles sollte gut sein.
quelle
If-Modified-Since
GET-Anforderung wird an den Ursprung gesendet) um einen Server wie in Schritt 5Es ist tangential, aber hier ist ein Tipp für diejenigen, die Rackt's React Router-Bibliothek mit (HTML5) Browserverlauf verwenden und auf S3 hosten möchten.
Angenommen, ein Benutzer besucht
/foo/bear
Ihre von S3 gehostete statische Website. Aufgrund des früheren Vorschlags Davids werden sie von Umleitungsregeln an gesendet/#/foo/bear
. Wenn Ihre Anwendung mithilfe des Browserverlaufs erstellt wurde, hilft dies nicht viel. Ihre Anwendung ist jedoch zu diesem Zeitpunkt geladen und kann nun den Verlauf bearbeiten.Wenn Sie den Rackt- Verlauf in unser Projekt aufnehmen (siehe auch Verwenden von benutzerdefinierten Verlaufsdaten aus dem React Router-Projekt), können Sie einen Listener hinzufügen, der die Hash-Verlaufspfade kennt, und den Pfad entsprechend ersetzen, wie in diesem Beispiel dargestellt:
Um es noch einmal zusammenzufassen:
/foo/bear
an weitergeleitet/#/foo/bear
.#/foo/bear
Verlaufsnotation.Link
Tags funktionieren wie erwartet, ebenso wie alle anderen Browserverlaufsfunktionen. Der einzige Nachteil, den ich bemerkt habe, ist die interstitielle Umleitung, die bei der ersten Anforderung erfolgt.Dies wurde von einer Lösung für AngularJS inspiriert , und ich vermute, dass sie leicht an jede Anwendung angepasst werden kann.
quelle
browserHistory.listen
Ich sehe 4 Lösungen für dieses Problem. Die ersten 3 wurden bereits in Antworten behandelt und die letzte ist mein Beitrag.
Setzen Sie das Fehlerdokument auf index.html.
Problem : Der Antworttext ist korrekt, aber der Statuscode lautet 404, was der SEO schadet.
Legen Sie die Umleitungsregeln fest.
Problem : URL verschmutzt mit
#!
und Seite blinkt beim Laden.Konfigurieren Sie CloudFront.
Problem : Alle Seiten geben 404 vom Ursprung zurück. Sie müssen also auswählen, ob Sie nichts zwischenspeichern möchten (TTL 0 wie vorgeschlagen) oder ob Sie beim Aktualisieren der Site zwischenspeichern und Probleme haben.
Alle Seiten vorrendern.
Problem : Zusätzliche Arbeit zum Vorrendern von Seiten, insbesondere wenn sich die Seiten häufig ändern. Zum Beispiel eine Nachrichten-Website.
Mein Vorschlag ist, Option 4 zu verwenden. Wenn Sie alle Seiten vorrendern, treten für die erwarteten Seiten keine 404-Fehler auf. Die Seite wird gut geladen und das Framework übernimmt die Kontrolle und fungiert normal als SPA. Sie können das Fehlerdokument auch so einstellen, dass eine generische error.html-Seite und eine Umleitungsregel zum Umleiten von 404-Fehlern auf eine 404.html-Seite (ohne Hashbang) angezeigt werden.
In Bezug auf 403 Verbotene Fehler lasse ich sie überhaupt nicht zu. In meiner Anwendung, denke ich , dass alle Dateien innerhalb der Host - Eimer sind öffentlich und ich setze diese mit dem jeder Option mit der Leseberechtigung. Wenn Ihre Site über private Seiten verfügt, sollte es kein Problem sein , dem Benutzer das HTML- Layout anzuzeigen. Was Sie schützen müssen, sind die Daten, und dies erfolgt im Backend.
Wenn Sie über private Assets wie Benutzerfotos verfügen, können Sie diese in einem anderen Bucket speichern . Weil private Assets die gleiche Sorgfalt wie Daten benötigen und nicht mit den Asset-Dateien verglichen werden können, die zum Hosten der App verwendet werden.
quelle
Ich bin heute auf dasselbe Problem gestoßen, aber die Lösung von @ Mark-Nutter war unvollständig, um den Hashbang aus meiner AngularJS-Anwendung zu entfernen.
Tatsächlich müssen Sie zu Berechtigungen bearbeiten gehen , auf Weitere Berechtigungen hinzufügen klicken und dann allen die richtige Liste in Ihrem Bucket hinzufügen . Mit dieser Konfiguration kann AWS S3 nun 404-Fehler zurückgeben, und die Umleitungsregel erkennt den Fall ordnungsgemäß.
Genau wie dieser :
Anschließend können Sie unter Umleitungsregeln bearbeiten die folgende Regel hinzufügen:
Hier können Sie den Hostnamen subdomain.domain.fr durch Ihre Domain und das KeyPrefix #! / Ersetzen, wenn Sie die Hashbang-Methode nicht für SEO-Zwecke verwenden.
All dies funktioniert natürlich nur, wenn Sie html5mode bereits in Ihrer Winkelanwendung eingerichtet haben.
quelle
Die einfachste Lösung, um Angular 2+ -Anwendungen, die von Amazon S3 und direkten URLs bereitgestellt werden, funktionsfähig zu machen, besteht darin, index.html sowohl als Index- als auch als Fehlerdokumente in der S3-Bucket-Konfiguration anzugeben.
quelle
body
die Antwort. Der Statuscode wird 404 sein und es wird SEO schaden.body
wenn Sie Skripte haben, die Sie in die importieren,head
funktionieren diese nicht, wenn Sie direkt auf eine derda das problem immer noch da ist, werfe ich aber eine andere lösung ein. Mein Fall war, dass ich alle Pull-Anforderungen zum Testen automatisch auf s3 bereitstellen wollte, bevor sie zusammengeführt wurden, um sie unter [mydomain] / pull-request / [pr number] /
(z. B. www.example.com/pull-requests/822/) zugänglich zu machen . )
Nach meinem besten Wissen würden Szenarien ohne s3-Regeln es ermöglichen, mehrere Projekte mithilfe von HTML5-Routing in einem Bucket zu haben. Während der oben genannte Vorschlag für ein Projekt im Stammordner funktioniert, gilt dies nicht für mehrere Projekte in eigenen Unterordnern.
Also habe ich meine Domain auf meinen Server verwiesen, auf dem die folgende nginx-Konfiguration den Job erledigt hat
Es versucht, die Datei abzurufen, und wenn es nicht gefunden wird, geht es davon aus, dass es sich um eine HTML5-Route handelt, und versucht dies. Wenn Sie eine 404-Winkelseite für nicht gefundene Routen haben, gelangen Sie nie zu @not_found und erhalten eine eckige 404-Seite zurück, anstatt nicht gefundene Dateien, die mit einigen if-Regeln in @get_routes oder so behoben werden könnten.
Ich muss sagen, dass ich mich im Bereich der Nginx-Konfiguration und der Verwendung von Regex nicht besonders wohl fühle. Ich habe dies mit einigem Ausprobieren zum Laufen gebracht. Während dies funktioniert, bin ich sicher, dass es Raum für Verbesserungen gibt, und bitte teilen Sie Ihre Gedanken mit .
Hinweis : Entfernen Sie die s3-Umleitungsregeln, wenn Sie sie in der S3-Konfiguration hatten.
und übrigens funktioniert in Safari
quelle
War auf der Suche nach der gleichen Art von Problem. Am Ende habe ich eine Mischung der oben beschriebenen Lösungsvorschläge verwendet.
Erstens habe ich einen S3-Bucket mit mehreren Ordnern, wobei jeder Ordner eine React / Redux-Website darstellt. Ich benutze Cloudfront auch für die Cache-Ungültigmachung.
Also musste ich Routing-Regeln zur Unterstützung von 404 verwenden und sie in eine Hash-Konfiguration umleiten:
In meinem js-Code musste ich mit einer
baseName
Konfiguration für den React -Router umgehen . Stellen Sie zunächst sicher, dass Ihre Abhängigkeiten interoperabel sind. Ich hatte sie installierthistory==4.0.0
, mit denen sie nicht kompatibel warreact-router==3.0.1
.Meine Abhängigkeiten sind:
Ich habe eine
history.js
Datei zum Laden des Verlaufs erstellt:Mit diesem Code können Sie die vom Server gesendeten 404 mit einem Hash behandeln und diese im Verlauf ersetzen, um unsere Routen zu laden.
Sie können diese Datei jetzt zum Konfigurieren Ihres Geschäfts und Ihrer Root-Datei verwenden.
Ich hoffe es hilft. Sie werden feststellen, dass ich bei dieser Konfiguration einen Redux-Injektor und einen Homebrew-Sagas-Injektor verwende, um Javascript asynchron über das Routing zu laden. Kümmere dich nicht um diese Zeilen.
quelle
Sie können dies jetzt mit Lambda @ Edge tun, um die Pfade neu zu schreiben
Hier ist eine funktionierende Lambda @ Edge-Funktion:
In Ihrem Cloudfront-Verhalten bearbeiten Sie sie, um dieser Lambda-Funktion auf "Viewer-Anforderung" einen Aufruf hinzuzufügen.
Vollständiges Tutorial: https://aws.amazon.com/blogs/compute/implementing-default-directory-indexes-in-amazon-s3-backed-amazon-cloudfront-origins-using-lambdaedge/
quelle
return callback(null, request);
Wenn Sie hier gelandet sind und nach einer Lösung suchen, die mit React Router und AWS Amplify Console funktioniert, wissen Sie bereits, dass Sie die CloudFront-Umleitungsregeln nicht direkt verwenden können, da Amplify Console CloudFront Distribution für die App nicht verfügbar macht.
Die Lösung ist jedoch sehr einfach: Sie müssen lediglich eine Umleitungs- / Umschreiberegel in Amplify Console wie folgt hinzufügen:
Weitere Informationen (und eine kopierfreundliche Regel aus dem Screenshot) finden Sie unter den folgenden Links:
quelle
Ich habe selbst nach einer Antwort gesucht. S3 scheint nur Weiterleitungen zu unterstützen. Sie können die URL nicht einfach neu schreiben und stillschweigend eine andere Ressource zurückgeben. Ich denke darüber nach, mein Build-Skript zu verwenden, um einfach Kopien meiner index.html an allen erforderlichen Pfadpositionen zu erstellen. Vielleicht funktioniert das auch für Sie.
quelle
Nur um die extrem einfache Antwort zu formulieren. Verwenden Sie einfach die Hash-Standortstrategie für den Router, wenn Sie auf S3 hosten.
export const AppRoutingModule: ModuleWithProviders = RouterModule.forRoot (Routen, {useHash: true, scrollPositionRestoration: 'enabled'});
quelle