【问题标题】:Why does a change under the public folder triggers auto reload?为什么公用文件夹下的更改会触发自动重新加载?
【发布时间】:2014-06-09 10:10:28
【问题描述】:

我目前正在使用 Play Framework 2.3.0 和 AngularJS 开发一个网络应用程序。我使用 Play Framework 的 /public 文件夹来为我的 AngularJS 应用程序提供服务。

我在开发过程中所做的每一次更改都会触发 Play 完全重新加载,这有点烦人,因为我在 Global.beforeStart 方法中进行了耗时的计算。

为什么它会触发自动重新加载,因为正如the Play 2.3.0 documentation 所说:

存储在public 目录中的资源是静态资产,它们是 由 Web 服务器直接提供服务。

知道如何禁用public 文件夹的自动重新加载功能吗?

编辑:另一个想法:有没有办法从外部文件夹中提供资源,而该外部文件夹不受 Assets 控制器的监控?

【问题讨论】:

  • 它可能会有所帮助(frmo How are public assets packaged?):“在构建过程中,公用文件夹的内容被处理并添加到应用程序类路径中。”我读到Play在处理文件后从类路径访问资产并监控公共目录。
  • 感谢您的评论。我了解 Play 需要 /public 文件夹位于类路径中的事实。虽然它为什么触发自动重新加载不是很容易理解,因为它包含的资源据说是静态。有没有办法从使用 Assets 控制器监控的外部文件夹中提供资源?我还没有找到方法。
  • 目前已知issue。希望尽快修复。

标签: java playframework-2.0 sbt


【解决方案1】:

重新加载不是文件更改触发,它们由类路径更改触发。当然,源文件更改可能会触发类路径更改,但也可能不会。

Play 的运行模式是监视所有源文件的更改,这包括对公共目录和资产的更改,因为可能需要对这些文件进行处理。每当发生变化时,它都会要求 sbt 重新编译——这意味着重新编译所有内容,包括静态资产和 scala/java 文件。

当 sbt 重新编译时,它使用增量编译 - 这意味着,它存储最后一次编译的结果,并查看它以确定自上次编译以来是否有任何新工作需要完成。如果没有,则跳过编译。

将资源从资源目录复制到类路径也是如此。

所以,在 Play 要求 sbt 重新编译之后,它会检查 - 类路径是否有任何更改?如果有,它会重新加载。但是,如果您更改的只是一个 javascript 文件,那么就不应该有。

但是,您不是唯一更改文件的人 - 如果您已将 SBT 配置为为您生成一些文件,可能是 Java/Scala 源文件,或者可能只是 conf 目录中的一些资源,以及您的任务我写过每次都这样做,不管它是否需要这样做——这可能是一个类路径的改变。

因此,要解决您的问题,请检查您编写的任何任务或您正在使用的任何插件,看看它们是否正在生成源或资源。如果他们是,并且他们对此并不聪明,即他们在不需要时重新生成相同的文件,那么这可能会导致 Play 在任何源文件更改时重新加载,因为这意味着每个当 sbt 重新编译时,文件被重新生成,这改变了类路径。

【讨论】:

  • 如果我在子项目的公共目录中touch .js 文件,它会触发完全重新编译并重新启动。除了enablePlugins(PlayScala)routesGeneratorfork in run := true 之外,我没有启用任何其他功能。还有什么可以触发它的吗?
【解决方案2】:

也许您正在(或曾经)使用 BuildInfoPlugin? (或者也许其他发现这个问题的人,使用它)

每当我触摸public/ 中的任何内容时,Play Framework 总是为我重新启动。最终我注意到这是因为我正在使用 SBT BuildInfoPlugin https://github.com/sbt/sbt-buildinfo,并将其配置为在生成的构建信息中包含构建时间戳和 git status。在我删除了构建信息的这些部分后,在 public/ 发生更改后,Play 不再重新编译或重新加载。

这适用于 SBT 0.13.15 和 SBT 1.1.1,以及 Play Framework 2.6.9 和 2.6.12。

这是我删除的内容:
buildInfoOptions += BuildInfoOption.BuildTime
和:
BuildInfoKey.action("gitStatus") { "git status".!!.trim }).

(我不需要为 Play 配置 watchSourcesplayMonitoredFiles 来停止重新编译和重新加载。)

【讨论】:

    【解决方案3】:

    我在 build.sbt 中添加了以下内容:

        watchSources := (watchSources.value
          --- baseDirectory.value / "public"     ** "*").get
    

    它将从正在监视的文件夹列表中删除“/public”。请注意,这可能会破坏某些内容,但在问题得到解决之前,这是一个很好的解决方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多