Play フレームワーク 2.2.x:静的アセットの場所が本番環境で機能しない
-
21-12-2019 - |
質問
本番環境でコンパイルされたアセットの場所にアクセスできない。
私の戦略は、開発時は「app/assets/ui」でアセットを提供し、運用時は「public」で提供することであり、これは私の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"
次に、パッケージ化されたアプリを実行します。
私の問題は、ルートが依然としてディストリビューションの「public」フォルダーではなく「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
適切な値が含まれており、そのうちの 1 つはベースです 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
つまり、現在の動作モードを評価し、マップ検索を 1 回行うだけで済みます。
今あなたの routes
ファイルは次のようになります。
GET /assets/*file controllers.EnvironmentSpecificAssets.at(file)
他のヒント
PlayFramework 2.xはルートファイル内の条件文をサポートしません。1.xバージョンはこれを持っていましたが、削除されました。
routesファイルにあるものは、同じURIパターン、/assets/file*
を持つ2つのルートです。他の行は、ポンド文字、#
で始まるため、コメントとして無視されています。私は最初のルートの両方がすべてをキャッチしているのでパターンが同じであると思います、そして2番目は何もしていません。
あなたがしようとしていることは正確ではありませんが、私はあなたがルートパターンを少し異なるようにすることができ、それは仕事をするべきです。
GET /assets/dev/*file controllers.common.Assets.at(path="/app/assets/ui", file)
GET /assets/*file controllers.common.Assets.at(path="/public", file)
.