Gioca a Framework 2.2.x:La posizione delle risorse statiche non funziona in produzione
-
21-12-2019 - |
Domanda
Problemi di accesso alla posizione delle risorse compilate in produzione.
La mia strategia è stata quella di servire le mie risorse in "app/assets/ui" durante lo sviluppo e "pubblico" durante la produzione, ciò avviene come mostrato di seguito nel mio file conf/routes
#{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)
#{/}
Poiché ho definito le mappature delle risorse al di fuori di "pubblico", ho aggiunto la seguente riga nel mio Build.scala
playAssetsDirectories <+= baseDirectory / "app/assets/ui"
Ad esempio, i miei script vengono caricati in modo condizionale a seconda dell'ambiente, come mostrato di seguito
@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>}
Sto utilizzando Grunt per il mio flusso di lavoro frontend e quando l'applicazione viene creata copia i file di distribuzione nella cartella pubblica dell'applicazione.Avvio l'app in produzione utilizzando "sbt clean compile stage"
e quindi eseguire l'app in pacchetto.
Il mio problema sembra che i percorsi facciano ancora riferimento alla cartella "app/assets/ui" anziché alla cartella "pubblica" della distribuzione.
Qualche consiglio su come posso eseguire il debug di questo?Il mio background lavorativo è come sviluppatore front-end, quindi sono completamente nuovo a Play!e scala.
Soluzione
Come menzionato da @estmatic, il tuo condizionale è in routes
non verrà valutato.
Poiché in genere è estremamente utile consolidare le differenze tra le applicazioni Mode
è in file, ti suggerisco di estenderlo GlobalSettings
(se non lo sei già) e sovrascrivi il file onLoadConfig
metodo:
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)
}
...
}
Potresti quindi avere file con nomi appropriati (dev.conf
E production.conf
mi vengono in mente) che contengono valori adeguati, uno dei quali è la base path
che il controller Assets possa utilizzare.
EDIT risulta che farlo in questo modo facilita l'utilizzo routes
imbarazzante, ecco un altro approccio:
Questo approccio non utilizza un file di configurazione per ambiente, il che significa che se qualcosa cambia nella configurazione del frontend (ad es.non viene più servito da /public
) dovrai modificare questo codice e ridistribuirlo.Tuttavia, si adatta abbastanza bene a 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)
}
Il codice è abbastanza autoesplicativo, l'unico "trucco" è probabilmente il file lazy val
ciò significa che dobbiamo solo valutare la modalità operativa corrente ed eseguire la ricerca della mappa una sola volta.
Adesso tuo routes
il file assomiglia a questo:
GET /assets/*file controllers.EnvironmentSpecificAssets.at(file)
Altri suggerimenti
PlayFramework 2.x non supporta le dichiarazioni condizionali nel file percorsi.Le versioni 1.x hanno avuto questo ma è stato rimosso.
Quello che hai nel tuo file di percorsi è semplicemente due percorsi con lo stesso modello URI, /assets/file*
.Le altre linee vengono semplicemente ignorate come commenti dal momento che iniziano con il personaggio della libbra, #
.Penso che dal momento che il modello è lo stesso per entrambi il primo percorso sta prendendo tutto e il secondo non sta facendo nulla.
Non è esattamente quello che stai cercando di fare, ma penso che tu possa semplicemente rendere i motivi del percorso un po 'diversa e dovrebbe funzionare.
GET /assets/dev/*file controllers.common.Assets.at(path="/app/assets/ui", file)
GET /assets/*file controllers.common.Assets.at(path="/public", file)
.