我使用Sass作为我的CSS预处理程序,我试图让它通过资产管道运行。我已经尝试将此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
Sass编译为网络资产任务:
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)
答案 0 :(得分:7)
我认为根据与Asset Pipeline相关的文档,源文件任务是一种方法:
作为插件的源文件任务示例是CoffeeScript,LESS和 JSHint。其中一些采用源文件并生成目标Web 资产例如CoffeeScript生成JS文件。此类插件 在功能方面彼此互相排斥,即 只有一个CoffeeScript插件会使用CoffeeScript源代码 生成目标JS文件。总之,源文件插件产生web 资产。
我认为你试图实现的目标属于这一类。
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
假设您在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
}
但这还不够。如果您想保留目录结构,则必须将sassOutputDir
添加到resourceDirectories 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
}
这意味着所有未映射的文件都使用alternative flat
策略进行映射。但是,修复它很简单,只需将其添加到build.sbt
resourceDirectories in Assets += sassOutputDir.value
这将确保保留目录结构。