【问题标题】:Custom sbt task that compiles JavaScript and is activated only in production mode编译 JavaScript 并仅在生产模式下激活的自定义 sbt 任务
【发布时间】:2016-08-24 23:05:20
【问题描述】:

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

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

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

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

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

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

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

有什么想法吗?

【问题讨论】:

    标签: scala playframework webpack sbt


    【解决方案1】:

    因此,应该依赖于我的自定义任务(构建 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 中,最后缺少的一块是根据当前模式加载正确的 JavaScript 文件(在生产模式下,您需要编译的包,在开发中模式,您需要将页面指向webpack 服务器)。关键是,为了利用所有 webpack 功能(如热重载和热 React 组件替换),您不能通过 Scala Play 服务器从静态文件中提供 JavaScript,它必须是 @ 987654333@ 服务器。从理论上讲,可以将 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>
    }
    

    【讨论】:

      猜你喜欢
      • 2018-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-02
      • 1970-01-01
      • 2015-10-03
      • 2016-04-18
      • 1970-01-01
      相关资源
      最近更新 更多