Question

Difficulté à accéder à l’emplacement des actifs compilés en production.

Ma stratégie a été de servir mes actifs dans "app/assets/ui" en développement et "public" en production, comme indiqué ci-dessous dans mon fichier 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)
#{/}

Depuis que j'ai défini les mappages d'actifs en dehors de « public », j'ai ajouté la ligne suivante dans mon Build.scala

playAssetsDirectories <+= baseDirectory / "app/assets/ui"

A titre d'exemple, mes scripts sont chargés de manière conditionnelle en fonction de l'environnement, comme indiqué ci-dessous

@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>}

J'utilise Grunt pour mon flux de travail frontal et lorsque l'application est créée, elle copie les fichiers de distribution dans le dossier public de l'application.Je démarre l'application en production en utilisant "sbt clean compile stage" puis exécutez l'application packagée.

Mon problème semble que les routes font toujours référence au dossier "app/assets/ui" au lieu du dossier "public" de distribution.

Des conseils sur la façon dont je peux déboguer cela ?Mon expérience professionnelle est celle de développeur front-end, je suis donc très nouveau sur Play !et Scala.

Était-ce utile?

La solution

Comme mentionné par @estmatic, votre conditionnel dans routes ne sera pas évalué.

Comme il est généralement extrêmement utile de consolider les différences entre les applications Modes dans les fichiers, je vous suggère d'étendre GlobalSettings (si ce n'est pas déjà fait) et remplacez le onLoadConfig méthode:

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)
  }
  ...
}

Vous pourriez alors avoir des fichiers nommés de manière appropriée (dev.conf et production.conf me viennent à l'esprit) qui contiennent des valeurs appropriées, l'une d'entre elles étant la base path pour que le contrôleur d'actifs puisse l'utiliser.

EDIT s'avère que le faire de cette façon permet d'utiliser routes gênant, voici une autre approche :

Cette approche n'utilise pas de fichier de configuration par environnement, ce qui signifie que si quelque chose change dans la configuration du frontend (par ex.il n'est plus servi de /public) vous devrez modifier ce code et le redéployer.Cependant, il s'intègre assez bien dans 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)
}

Le code est assez explicite, le seul "truc" est probablement le lazy val ce qui signifie que nous n'avons qu'à évaluer le mode de fonctionnement actuel et à effectuer la recherche sur la carte une seule fois.

Maintenant votre routes le fichier ressemble à ceci :

GET   /assets/*file     controllers.EnvironmentSpecificAssets.at(file)

Autres conseils

Playframework 2.x ne prend pas en charge les instructions conditionnelles dans le fichier routes.Les versions 1.x l'avaient mais il a été supprimé.

Ce que vous avez dans votre fichier de routes, ce sont simplement deux routes avec le même modèle d'URI, /assets/file*.Les autres lignes sont simplement ignorées en tant que commentaires puisqu'elles commencent par le caractère dièse, #.Je pense que puisque le modèle est le même pour les deux, le premier itinéraire attrape tout et le second ne fait rien.

Ce n'est pas exactement ce que vous essayez de faire, mais je pense que vous pouvez simplement rendre les modèles d'itinéraire un peu différents et cela devrait fonctionner.

GET   /assets/dev/*file   controllers.common.Assets.at(path="/app/assets/ui", file)
GET   /assets/*file       controllers.common.Assets.at(path="/public", file)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top