2017-11-02 4 views
0

Ich versuche, eine React-Site von einem Play Framework-Server aus zu hosten. Das React-Front-End wird in einem separaten Projekt entwickelt und seine Build-Artefakte (statische html/js/css/etc. Dateien) werden in den Ordner public des Play-Projekts kopiert.So erstellen Sie die try_files von nginx in Play Framework neu, um die React-Site zu hosten

Jetzt habe ich versucht, z./page1 (wo das eine React-Route ist), aber ich bekomme einen 404, weil der Server natürlich keine solche Route hat.

Was ich will, ist Nginx try_files $uri /index.html Art der Funktionalität zu replizieren - wenn der Pfad, der gefragt wird, bedient werden kann (d. H. Es entspricht einem Asset, das der Server kennt), wird es serviert. Sonst, serviere den Inhalt von index.html ohne die URL neu schreiben, so dass React's Routing funktionieren kann.

Ich habe versucht, dies mit nur der Datei und auch als Controller (mit einem if/sonst) zu arbeiten. Ich konnte nicht genau replizieren, was in nginx ein Einzeiler ist. Wie könnte ich das tun?

Antwort

2

Wie @vdebergue sagt, können Sie eine vereinfachte Version von dem, was Sie wollen durch Hinzufügen eines Catch-All an der unten Ihrer conf/routes Datei .

jedoch wenn Sie andere Dateien in public haben, die Sie immer noch richtig sein möchten (zB Bilddateien), benötigen Sie etwas mehr zu bedienen mächtig serviert.

Ich habe darüber in my blog in July geschrieben, aber nach Stack Overflow-Konvention werde ich es auch hier erweitern. Grundsätzlich können Sie this Gist kopieren, die eine FrontEndServingController deklariert.

Die wichtigsten Funktionen, die diese Steuerung über die Steuerung integrierte in Assets gibt, ist, dass bei der ersten Verwendung, ist es Ihre public Verzeichnis rekursiv durchsucht echte Dateien zu finden, so weiß sie, wenn sie servieren, und wenn dienen up index.html (Ihre React App).

Dann nutzen Sie es in Ihrem routes-Datei wie folgt:

GET/  controllers.FrontEndServingController.index 
GET /*file controllers.FrontEndServingController.frontEndPath(file) 
+1

Dies funktionierte perfekt im" dev mode ", scheiterte aber im prod mode. Insbesondere scheint es, dass Sie 'f.listFiles' in Zeile 25 Ihres Gist nicht verwenden können, es explodiert mit einer' NullPointerException'. Ich musste den Gist wie folgt modifizieren, um es sowohl für den Dev- als auch den Prod-Modus arbeiten zu lassen: https://gist.github.com/mrubin/211f007508cd90f471d697132727808c – iraxef

+1

Beachten Sie, dass Sie den expliziten 'Index' loswerden könnten Route, wenn Sie wollten, wenn Sie die Route wie folgt umgeschrieben: 'GET/$ Pfad <.*> controllers.FrontEndServingController.frontEndPath (Pfad)' – iraxef

+0

Danke für die Beiträge und Vorschläge @iraxef! – millhouse

-1

Sie können es einfach in der Routendatei tun. Am unteren Rand der Datei, fügen Sie diese fangen alle Regel:

# your other routes above 
# ... 
GET  /$any<.*>    controllers.Assets.at(path="/public", file="index.html") 
+0

Das funktioniert nicht: 'Übersetzungsfehler [Fehlende Parameter in Call-Definition: beliebige] [Fehler] GET/$ alle <.*> Controller .Assets.at (path = "/ public", file = "index.html") ' – iraxef

Verwandte Themen