Play Framework 2.2.x:Der Standort der statischen Assets funktioniert in der Produktion nicht
-
21-12-2019 - |
Frage
Es gibt Probleme beim Zugriff auf den Speicherort der kompilierten Assets in der Produktion.
Meine Strategie bestand darin, meine Assets in der Entwicklung in „app/assets/ui“ und in der Produktion in „public“ bereitzustellen. Dies geschieht wie unten in meiner conf/routes-Datei gezeigt
#{if(play.Play.mode.isDev())}
GET /assets/*file controllers.common.Assets.at(path="/app/assets/ui", file)
#{/}
#{else}
GET /assets/*file controllers.common.Assets.at(path="/public", file)
#{/}
Da ich Asset-Zuordnungen außerhalb von „öffentlich“ definiert habe, habe ich die folgende Zeile in meine Build.scala eingefügt
playAssetsDirectories <+= baseDirectory / "app/assets/ui"
Als Beispiel werden meine Skripte abhängig von der Umgebung bedingt geladen, wie unten gezeigt
@if(play.Play.isDev()) {<script src="@routes.Assets.at("/app/assets/ui", "javascripts/application.js")"type="text/javascript"></script>} else {<script src="@.routes.Assets.at("/public", "javascripts/application.min.js")" type="text/javascript"></script>}
Ich verwende Grunt für meinen Frontend-Workflow und kopiert beim Erstellen der Anwendung die Verteilungsdateien in den öffentlichen Ordner der Anwendung.Ich starte die App in der Produktion mit "sbt clean compile stage"
und führen Sie dann die gepackte App aus.
Mein Problem scheint, dass die Routen immer noch auf den Ordner „app/assets/ui“ und nicht auf den Verteilungsordner „public“ verweisen.
Irgendwelche Tipps, wie ich das debuggen kann?Mein beruflicher Hintergrund ist ein Front-End-Entwickler, daher bin ich ganz neu bei Play!und Scala.
Lösung
Wie von @estmatic erwähnt, ist Ihre Bedingung in routes
wird nicht ausgewertet.
Da es im Allgemeinen äußerst nützlich ist, die Unterschiede zwischen Anwendungen zu konsolidieren Mode
s in Dateien, ich würde vorschlagen, dass Sie sie erweitern GlobalSettings
(falls noch nicht geschehen) und überschreiben Sie die onLoadConfig
Methode:
class Settings extends GlobalSettings {
override def onLoadConfig(config: Configuration, path: File, classloader: ClassLoader, mode: Mode.Mode): Configuration = {
val specificConfig:Config = // ... Use the mode param to load appropriate file
super.onLoadConfig(specificConfig, path, classloader, mode)
}
...
}
Sie könnten dann entsprechend benannte Dateien haben (dev.conf
Und production.conf
(die mir in den Sinn kommen), die geeignete Werte enthalten, von denen einer die Basis ist path
für den Assets-Controller zur Verwendung.
Es stellt sich heraus, dass EDIT auf diese Weise die Verwendung erleichtert routes
umständlich, hier ist ein anderer Ansatz:
Dieser Ansatz verwendet keine Konfigurationsdatei pro Umgebung, was bedeutet, dass bei Änderungen in der Frontend-Konfiguration (z. B.es wird nicht mehr serviert /public
) müssen Sie diesen Code ändern und erneut bereitstellen.Es passt jedoch ziemlich gut in Play 2.x:
package controllers
object EnvironmentSpecificAssets extends AssetsBuilder {
val modeToAssetsPathMap = Map(
Mode.Dev -> "/app/assets/ui",
Mode.Prod -> "/public")
lazy val modePath = modeToAssetsPathMap(Play.current.mode)
/** New single-argument `at`, determines its path from the current app mode */
def at(file:String): Action[AnyContent] = at(modePath, file)
}
Der Code ist ziemlich selbsterklärend, der einzige „Trick“ ist wahrscheinlich der lazy val
Das heißt, wir müssen nur einmal den aktuellen Betriebsmodus auswerten und die Kartensuche durchführen.
Jetzt dein routes
Die Datei sieht einfach so aus:
GET /assets/*file controllers.EnvironmentSpecificAssets.at(file)
Andere Tipps
playframework 2.x unterstützt keine bedingten Anweisungen in der Routes-Datei.Die 1.x-Versionen hatten dies, aber es wurde entfernt.
Was Sie in Ihrer Routes-Datei haben, ist einfach zwei Routen mit demselben URI-Muster, generationspflichtig.Die anderen Linien werden nur als Kommentare ignoriert, da sie mit dem Pfund-Charakter, generas, generationspflichtig, generakodicetagcode beginnen.Ich denke, da das Muster für beide der erste Route das Gleiche ist, ist alles, was alles fängt und der zweite nichts tut.
Es ist nicht genau das, was Sie tun wollen, aber ich denke, Sie können einfach die Routenmuster etwas anders machen und es sollte funktionieren.
generasacodicetagpre.