从SBT Web生成静态资产



我有一个基于SBT-Web和Play框架的项目。那么,Play只是用于开发,然后(当在SBT/Activator中运行stage命令时)所有内容都导出到静态页面并部署到一些甚至可能没有安装Java的web服务器。

我当前的方法是添加一个resourceGenerator:

resourceGenerators in Assets += Def.task {
  for(year <- PageGenerator.Years) yield {
    val file = (resourceManaged in Assets).value / "assets" / s"${year.year}.html"
    println(s"Writing $file…")
    IO.write(file, PageGenerator.forYear(year))
    file
  }
}.taskValue

现在可以工作了,但是它有一些缺点:

    首先,我不能使用子目录。当我尝试将文件放入子目录时,它被放在根目录下。
  • 当我更改模板或源数据时,我必须重新加载项目以使其有效。
  • 最后,我会稍微欣赏使用Twirl或类似的东西。

如何克服这些缺点?第一个是最重要的。)

  • 我试图把生成代码到管道阶段。这在构建最终工件时有效,但在开发期间不起作用。
  • 想法:使用Twirl模板,在开发过程中动态调用它,并在管道阶段以某种方式调用它(使用一些ClassLoader和Reflection API)。我不确定这是不是正确的方法。我保证Scala/Twirl代码已经编译时执行sbt-web管道阶段?
  • 一个古怪的想法:生成项目根的文件,在开发模式下通过路由动态地服务它们,在管道阶段重命名它们。这是一个沉重的hack,但它应该工作,在理论上。

好了,找到解决主要问题的办法了:

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

但是,它并没有解决其他的问题,所以欢迎其他的答案。

对于遇到此问题的任何人,以下是@v6ak提到的解决方案的重要部分:

为了防止文件总是被放置在公共根目录中,即使它们被放置在子目录中,您还必须将任务输出的目录添加到resourceDirectories

val taskOutputDir = settingKey[File]("Resource directory for task output")
taskOutputDir  := (resourceManaged in Assets).value / "my-task"

// ADD THIS to preserve directory structure
resourceDirectories in Assets += taskOutputDir.value

resourceGenerators in Assets += Def.task {
  // Generate your assets and output them to 'taskOutputDir'
  // return a Seq[File] of the generated files
}.taskValue

最新更新