在Play中通过"activator run"运行时获取要编译的资源

acj*_*jay 4 scala sbt playframework sbt-web

我正在使用Sass作为我的CSS preprocesser,我正试图让它通过资产管道运行.我已经尝试将这个sassTask实现为源文件任务和Web资产任务,但我遇到了两个方面的问题.

如果我将Sass作为源任务运行(见下文),它会在activator run请求页面时触发,并在页面重新加载时找到更新的文件.我遇到的问题是生成的CSS文件都被直接转储target/web/public/main/lib到子目录中,而不是反映在它们内置到resources-managed目录下的子目录中.我无法弄清楚如何实现这一目标.

相反,我尝试将Sass编译实现为Web资产任务(见下文).据我所知,以这种方式工作resources-managed并没有发挥作用,所以我将我的文件直接编译成target/web/public/main/lib.我确定我没有足够动态地做这件事,但我不知道怎么做得更好.但这里最大的问题是管道在完成工作时显然不会运行activator run.我可以让它运行使用activator stage,但我真的需要它在常规开发工作流程中工作,以便我可以在开发服务器运行时更​​改样式文件,与Scala文件相同.

我试过梳理这些论坛,通过sbt-web文档,以及一些现有的插件,但我发现这个过程非常令人沮丧,因为SBT的复杂性和实际发生的事情的不透明性.构建过程.

Sass编译作为源文件任务:

lazy val sassTask = TaskKey[Seq[java.io.File]]("sassTask", "Compiles Sass files")

sassTask := {
  import sys.process._
  val x = (WebKeys.nodeModules in Assets).value
  val sourceDir = (sourceDirectory in Assets).value
  val targetDir = (resourceManaged in Assets).value
  Seq("sass", "-I", "target/web/web-modules/main/webjars/lib/susy/sass", "--update", s"$sourceDir:$targetDir").!
  val sources = sourceDir ** "*.scss"
  val mappings = sources pair relativeTo(sourceDir)
  val renamed = mappings map { case (file, path) => file -> path.replaceAll("scss", "css") }
  val copies = renamed map { case (file, path) => file -> targetDir / path }
  copies map (_._2)
}

sourceGenerators in Assets <+= sassTask
Run Code Online (Sandbox Code Playgroud)

Sass编译为Web资产任务:

lazy val sassTask = taskKey[Pipeline.Stage]("Compiles Sass files")

sassTask := {
  (mappings: Seq[PathMapping]) =>
    import sys.process._
    val sourceDir = (sourceDirectory in Assets).value
    val targetDir = target.value / "web" / "public" / "main"
    val libDir = (target.value / "web" / "web-modules" / "main" / "webjars" / "lib" / "susy" / "sass").toString
    Seq("sass", "-I", libDir, "--update", s"$sourceDir:$targetDir").!
    val sources = sourceDir ** "*.scss"
    val mappings = sources pair relativeTo(sourceDir)
    val renamed = mappings map { case (file, path) => file -> path.replaceAll("scss", "css") }
    renamed
}

pipelineStages := Seq(sassTask)
Run Code Online (Sandbox Code Playgroud)

lpi*_*ora 7

我认为根据与资产管道相关的文档,源文件任务是一种方法:

作为插件的源文件任务的示例是CoffeeScript,LESS和JSHint.其中一些采用源文件并生成目标Web资源,例如CoffeeScript生成JS文件.此类别中的插件在功能方面彼此互斥,即只有一个CoffeeScript插件将使用CoffeeScript源并生成目标JS文件.总之,源文件插件产生Web资产.

我认为你试图实现的目标属于这一类.

TL; DR; - build.sbt

val sassTask = taskKey[Seq[File]]("Compiles Sass files")

val sassOutputDir = settingKey[File]("Output directory for Sass generated files")

sassOutputDir := target.value / "web" / "sass" / "main"

resourceDirectories in Assets += sassOutputDir.value

sassTask := {
  val sourceDir = (sourceDirectory in Assets).value
  val outputDir = sassOutputDir.value
  val sourceFiles = (sourceDir ** "*.scss").get
  Seq("sass", "--update", s"$sourceDir:$outputDir").!
  (outputDir ** "*.css").get
}

sourceGenerators in Assets += sassTask.taskValue
Run Code Online (Sandbox Code Playgroud)

说明

假设你在app/assets/<whatever>目录中有sass文件,并且你想在web/public/main/<whatever>目录中创建css文件,这就是你可以做的.

创建一个任务,该任务将读入app/assets/<whatever>目录和子目录中的文件,并将它们输出到我们定义的sassOutputDir.

val sassTask = taskKey[Seq[File]]("Compiles Sass files")

val sassOutputDir = settingKey[File]("Output directory for Sass generated files")

sassOutputDir := target.value / "web" / "sass" / "main"

resourceDirectories in Assets += sassOutputDir.value

sassTask := {
  val sourceDir = (sourceDirectory in Assets).value
  val outputDir = sassOutputDir.value
  val sourceFiles = (sourceDir ** "*.scss").get
  Seq("sass", "--update", s"$sourceDir:$outputDir").!
  (outputDir ** "*.css").get
}
Run Code Online (Sandbox Code Playgroud)

但这还不够.如果要保留目录结构,则必须将其添加sassOutputDirresourceDirectories in Assets.这是因为sbt-web中的映射声明如下:

mappings := {
  val files = (sources.value ++ resources.value ++ webModules.value) ---
    (sourceDirectories.value ++ resourceDirectories.value ++ webModuleDirectories.value)
  files pair relativeTo(sourceDirectories.value ++ resourceDirectories.value ++ webModuleDirectories.value) | flat
}
Run Code Online (Sandbox Code Playgroud)

这意味着所有未映射的文件都使用替代 flat策略进行映射.但是它的修复很简单,只需将其添加到您的build.sbt

resourceDirectories in Assets += sassOutputDir.value
Run Code Online (Sandbox Code Playgroud)

这将确保保留目录结构.

  • 天哪,伙计,你救了我的命。令人沮丧的是,我花了 48 小时试图弄清楚这一点,而且我阅读了整个 48 页的 SBT 教程。如果我阅读了整个文档,我想我最终可能会偶然发现这种行为,但我不得不说,SBT 幕后发生的所有“魔法”都非常令人沮丧。 (2认同)
  • @lpiepiora,非常感谢您的回答。这对我帮助很大! (2认同)