Платформа воспроизведения 2.2.x:Расположение статических ресурсов не работает в производстве
-
21-12-2019 - |
Вопрос
Возникли проблемы с доступом к расположению скомпилированных ресурсов в рабочей среде.
Моя стратегия заключалась в том, чтобы обслуживать мои активы в «app/assets/ui», когда они находятся в разработке, и в «публичных», когда они находятся в производстве. Это делается, как показано ниже в моем файле 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)
#{/}
Поскольку я определил сопоставления активов вне «public», я добавил следующую строку в свой Build.scala.
playAssetsDirectories <+= baseDirectory / "app/assets/ui"
Например, мои скрипты загружаются условно в зависимости от среды, как показано ниже.
@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>}
Я использую Grunt для рабочего процесса внешнего интерфейса, и при сборке приложения он копирует файлы дистрибутива в общую папку приложения.Я запускаю приложение в производстве, используя "sbt clean compile stage"
а затем запустите упакованное приложение.
Моя проблема заключается в том, что маршруты по-прежнему относятся к папке «app/assets/ui», а не к «общедоступной» папке распространения.
Любые советы о том, как я могу это отладить?Я работаю фронтенд-разработчиком, поэтому я новичок в Play!и скала.
Решение
Как упоминалось @estmatic, ваше условное выражение в routes
не будет оцениваться.
Поскольку обычно чрезвычайно полезно консолидировать различия между приложениями Mode
в файлы, я бы посоветовал вам расширить GlobalSettings
(если вы еще этого не сделали) и переопределите onLoadConfig
метод:
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)
}
...
}
Тогда вы могли бы иметь файлы с соответствующими именами (dev.conf
и production.conf
приходят на ум), которые содержат подходящие значения, одно из которых является базовым path
для использования контроллером активов.
РЕДАКТИРОВАТЬ, оказывается, делает это таким образом, что позволяет использовать routes
неудобно, вот еще один подход:
Этот подход не использует файл конфигурации для каждой среды, а это означает, что если что-то изменится в конфигурации внешнего интерфейса (например,его больше не подают из /public
) вам придется изменить этот код и повторно развернуть его.Однако он очень хорошо вписывается в 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)
}
Код довольно понятен, единственная «хитрость», вероятно, заключается в lazy val
это означает, что нам нужно только оценить текущий режим работы и выполнить поиск по карте один раз.
Теперь ваш routes
файл выглядит примерно так:
GET /assets/*file controllers.EnvironmentSpecificAssets.at(file)
Другие советы
Playframework 2.x не поддерживает условные операторы в файле маршрутов.В версиях 1.x это было, но было удалено.
В файле маршрутов у вас есть просто два маршрута с одинаковым шаблоном URI: /assets/file*
.Остальные строки просто игнорируются как комментарии, поскольку они начинаются с символа решетки. #
.Я думаю, поскольку схема одинакова: первый маршрут ловит все, а второй ничего не делает.
Это не совсем то, что вы пытаетесь сделать, но я думаю, вы можете просто немного изменить шаблоны маршрутов, и это должно сработать.
GET /assets/dev/*file controllers.common.Assets.at(path="/app/assets/ui", file)
GET /assets/*file controllers.common.Assets.at(path="/public", file)