إطار اللعب 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)
#{/}
منذ أن قمت بتحديد تعيينات الأصول خارج "العامة"، أضفت السطر التالي في 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
ليستخدمها مراقب الأصول.
EDIT تبين أن القيام بذلك بهذه الطريقة يجعل الاستخدام 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)