scala - 编译 JavaScript 并仅在生产模式下激活的自定义 sbt 任务

标签 scala playframework webpack sbt

我知道我可以编写自己的 sbt 任务,并且可以在它们之间创建依赖关系。任务层次结构对我来说似乎有点复杂,这就是我正在努力解决的问题:我不知道我的任务应该依赖于哪些任务。情况是这样的。

我的 Scala/Play 网络应用程序有一个相当复杂的前端,它是用 JavaScript/React 编写的,用 webpack 编译。在开发过程中,我正在使用 webpack-dev-server。它速度更快,并支持热重载等功能。然而,在生产模式下部署时,我想使用 sbt 构建我的前端。这意味着对于 sbt startsbt dist,我想让我的前端与 Scala 源代码一起编译,但是对于 sbt run 这个阶段应该完全省略(因为这会花费很多时间,而 webpack-dev-server 会负责)。

我创建了自己的 sbt 任务,它几乎只运行 npm install && npm run build 但我不知道在哪里 Hook 它。

我认为由于 sbt 处理“ Assets ”的方式,情况更加复杂。我的项目中有一个 public 文件夹,其中包含样式、脚本或图像等 Assets 。这些东西在构建过程中被复制到 target 文件夹,然后在最终的应用程序中可用。在我当前的解决方案中,原始 React/JavaScript 文件保持分离,自定义 sbt 任务将其编译到 public 文件夹中,编译后的包从那里复制到 target 文件夹.这是预期的工作流程,但此时必须手动调用自定义 sbt 任务。我想使整个过程自动化,但我不知道在将 JavaScript 复制到 target 文件夹之前,在哪里 Hook 我的任务来编译它。我尝试执行 copyResource 任务,如下所示:

(copyResources in Compile) <<= (copyResources in Compile) dependsOn buildJs

这似乎可行,但问题是自定义任务 (buildJs) 在开发模式下运行时也会被触发(即 sbt run)。这是我想避免的事情。

我尝试的另一种方法是将 JavaScript 直接编译到 target 文件夹中。这些文件出现在正确的位置,但应用程序并不知道它们。他们不可用。获取任何这些文件的 HTTP 请求返回空响应。

有什么想法吗?

最佳答案

因此,应该依赖于我的自定义任务(构建 JavaScript)的任务是 stagedist。这是我的 build.sbt:

lazy val buildJs = taskKey[Unit]("Build JavaScript frontend")
buildJs := {
  println("Building JavaScript frontend...")
  "npm install" #&& "npm run build" !
}

stage <<= stage dependsOn buildJs
dist <<= dist dependsOn buildJs

此任务仅对 sbt startsbt dist 激活,但对 sbt run(= 开发模式)不激活。为此,我使用了一个单独的 webpack-dev-server 实例来处理 JavaScript 编译。

可能有更简单的方法,但这对我有用。

如果您决定使用这种方式将 webpack 集成到 sbt 中,那么最后缺少的一 block 拼图是根据当前模式加载正确的 JavaScript 文件(在生产中模式下,需要编译好的bundle,开发模式下,需要将页面指向webpack服务器)。关键是,为了利用所有 webpack 功能(如热重载和热 React 组件替换),您不能通过 Scala Play 服务器从静态文件提供 JavaScript,它必须是 webpack 服务器。从理论上讲,可以将 Scala 服务器变成某种代理,但是,以下解决方案对我有用并且非常简单(index.scala.html 的一部分):

@if(play.Play.isDev()) {
    <script src="http://localhost:9090/webpack-dev-server.js"></script>
    <script src="http://localhost:9090/build/@{bundleName}.bundle.js"></script>
} else {
    <script src="@routes.Assets.versioned("javascripts/" + bundleName + ".bundle.js")"></script>
}

关于scala - 编译 JavaScript 并仅在生产模式下激活的自定义 sbt 任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36944218/

相关文章:

scala - 使用 scala fs2 文件流从文件中删除过滤行

java - 是否可以调试 Play!来自 IntelliJ 的测试,其模块位于子文件夹中?

scala - 在 Play 2 测试 + future 中捕获异常

json - 将 PostgreSQL JSON 类型与 Slick 2 代码生成器一起使用

scala - 使用 Redis 存储 ListBuffer[List[Double]]

angular - 在 Visual Studio 的 ASP.NET Core + Angular 2 模板上设置图像路径

reactjs - webpack:SASS 加载器失败 "Module build failed (from ./node_modules/sass-loader/lib/loader.js)"

webpack - React-Leaflet 与 Gatsby

scala - 从 Scala 中经过类型检查的具体化 `Tree` 中提取类型

scala - Play 2.0 中的子域