إطار اللعب 2.2.x:موقع الأصول الثابتة لا يعمل في الإنتاج

StackOverflow https://stackoverflow.com//questions/22018817

سؤال

تواجه مشكلة في الوصول إلى موقع الأصول المجمعة في الإنتاج.

كانت استراتيجيتي هي خدمة الأصول الخاصة بي في "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)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top