PlayRunHook 在多模块项目中不起作用
PlayRunHook does not work in multi module projects
我们需要一个基础 play 框架项目,其中包含其他 play 和 scala 项目作为模块。这些内部独立的项目可以有不同的 javascript 框架和构建系统,如 webpack、gulp 等
所以我尝试了 https://www.playframework.com/documentation/2.4.x/SBTCookbook 的 PlayRunHook。单个项目挂钩按预期工作。但是,无法在多模块项目上做到正确。一些代码示例...
项目结构
base/build.sbt
name := """base"""
version := "1.0-SNAPSHOT"
lazy val commonSettings = Seq(
scalaVersion := "2.11.6",
libraryDependencies ++= Seq(
jdbc,
cache,
ws,
specs2 % Test
),
resolvers ++= Seq(
"scalaz-bintray" at "http://dl.bintray.com/scalaz/releases"
)
)
lazy val root = (project in file("."))
.settings(commonSettings : _*)
.enablePlugins(PlayScala)
.dependsOn(scraper)
.aggregate(scraper)
.dependsOn(slider)
.aggregate(slider)
lazy val scraper = (project in file("modules/scraper"))
.settings(commonSettings : _*)
.enablePlugins(PlayScala)
lazy val slider = (project in file("modules/slider"))
.settings(commonSettings : _*)
.enablePlugins(PlayScala)
routesGenerator := InjectedRoutesGenerator
base/modules/scraper/build.sbt
import play.sbt.PlayImport.PlayKeys.playRunHooks
import WebPack._
name := """scraper"""
version := "1.0-SNAPSHOT"
lazy val frontendDirectory = baseDirectory {_ / "frontend"}
playRunHooks <+= frontendDirectory.map(WebPack.apply)
routesGenerator := InjectedRoutesGenerator
libraryDependencies ++= Seq(
"com.corundumstudio.socketio" % "netty-socketio" % "1.7.8"
)
resolvers ++= Seq(
"Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"
)
base/modules/slider/build.sbt
name := """slider"""
version := "1.0-SNAPSHOT"
scalaVersion := "2.11.6"
routesGenerator := InjectedRoutesGenerator
base/modules/scraper/project/WebPack.scala
import java.net.InetSocketAddress
import play.sbt.PlayRunHook
import sbt._
object WebPack {
def apply(base: File): PlayRunHook = {
object WebpackHook extends PlayRunHook {
var process: Option[Process] = None
override def beforeStarted(): Unit = {
if (isWindows) {
Process("cmd /c npm run compile", base).run
} else {
Process("npm run compile", base).run
}
}
override def afterStarted(addr: InetSocketAddress): Unit = {
if (isWindows) {
Some(Process("cmd /c npm start", base).run)
} else {
Some(Process("npm start", base).run)
}
}
private def isWindows: Boolean = {
System.getProperty("os.name").startsWith("Windows")
}
override def afterStopped(): Unit = {
process.foreach(_.destroy())
process = None
}
}
WebpackHook
}
}
但是我得到了
...../base/modules/scraper/build.sbt:10: error: not found: object WebPack
import WebPack._
^
sbt.compiler.EvalException: Type error in expression
at sbt.compiler.Eval.checkError(Eval.scala:384)
at sbt.compiler.Eval.compileAndLoad(Eval.scala:183)
at sbt.compiler.Eval.evalCommon(Eval.scala:152)
at sbt.compiler.Eval.evalDefinitions(Eval.scala:122)
at sbt.EvaluateConfigurations$.evaluateDefinitions(EvaluateConfigurations.scala:271)
at sbt.EvaluateConfigurations$.evaluateSbtFile(EvaluateConfigurations.scala:109)
at sbt.Load$.sbt$Load$$loadSettingsFile(Load.scala:712)
at sbt.Load$$anonfun$sbt$Load$$memoLoadSettingsFile.apply(Load.scala:717)
at sbt.Load$$anonfun$sbt$Load$$memoLoadSettingsFile.apply(Load.scala:716)
at scala.collection.MapLike$class.getOrElse(MapLike.scala:128)
at scala.collection.AbstractMap.getOrElse(Map.scala:58)
at sbt.Load$.sbt$Load$$memoLoadSettingsFile(Load.scala:716)
at sbt.Load$$anonfun$loadFiles.apply(Load.scala:723)
at sbt.Load$$anonfun$loadFiles.apply(Load.scala:723)
at scala.collection.TraversableLike$$anonfun$map.apply(TraversableLike.scala:244)
at scala.collection.TraversableLike$$anonfun$map.apply(TraversableLike.scala:244)
at scala.collection.immutable.List.foreach(List.scala:318)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
at scala.collection.AbstractTraversable.map(Traversable.scala:105)
at sbt.Load$.loadFiles(Load.scala:723)
at sbt.Load$.discoverProjects(Load.scala:734)
at sbt.Load$.discover(Load.scala:545)
at sbt.Load$.discoverAndLoad(Load.scala:554)
at sbt.Load$.loadTransitive(Load.scala:570)
at sbt.Load$.loadProjects(Load.scala:442)
at sbt.Load$.loadUnit(Load.scala:446)
at sbt.Load$$anonfun$$anonfun$apply.apply(Load.scala:281)
at sbt.Load$$anonfun$$anonfun$apply.apply(Load.scala:281)
at sbt.BuildLoader$$anonfun$componentLoader$$anonfun$apply$$anonfun$apply$$anonfun$apply.apply(BuildLoader.scala:91)
at sbt.BuildLoader$$anonfun$componentLoader$$anonfun$apply$$anonfun$apply$$anonfun$apply.apply(BuildLoader.scala:90)
at sbt.BuildLoader.apply(BuildLoader.scala:140)
at sbt.Load$.loadAll(Load.scala:334)
at sbt.Load$.loadURI(Load.scala:289)
at sbt.Load$.load(Load.scala:285)
at sbt.Load$.load(Load.scala:276)
at sbt.Load$.apply(Load.scala:130)
at sbt.Load$.defaultLoad(Load.scala:36)
at sbt.BuiltinCommands$.doLoadProject(Main.scala:481)
at sbt.BuiltinCommands$$anonfun$loadProjectImpl.apply(Main.scala:475)
at sbt.BuiltinCommands$$anonfun$loadProjectImpl.apply(Main.scala:475)
at sbt.Command$$anonfun$applyEffect$$anonfun$apply.apply(Command.scala:58)
at sbt.Command$$anonfun$applyEffect$$anonfun$apply.apply(Command.scala:58)
at sbt.Command$$anonfun$applyEffect$$anonfun$apply.apply(Command.scala:60)
at sbt.Command$$anonfun$applyEffect$$anonfun$apply.apply(Command.scala:60)
at sbt.Command$.process(Command.scala:92)
at sbt.MainLoop$$anonfun$$anonfun$apply.apply(MainLoop.scala:98)
at sbt.MainLoop$$anonfun$$anonfun$apply.apply(MainLoop.scala:98)
at sbt.State$$anon.process(State.scala:184)
at sbt.MainLoop$$anonfun.apply(MainLoop.scala:98)
at sbt.MainLoop$$anonfun.apply(MainLoop.scala:98)
at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17)
at sbt.MainLoop$.next(MainLoop.scala:98)
at sbt.MainLoop$.run(MainLoop.scala:91)
at sbt.MainLoop$$anonfun$runWithNewLog.apply(MainLoop.scala:70)
at sbt.MainLoop$$anonfun$runWithNewLog.apply(MainLoop.scala:65)
at sbt.Using.apply(Using.scala:24)
at sbt.MainLoop$.runWithNewLog(MainLoop.scala:65)
at sbt.MainLoop$.runAndClearLast(MainLoop.scala:48)
at sbt.MainLoop$.runLoggedLoop(MainLoop.scala:32)
at sbt.MainLoop$.runLogged(MainLoop.scala:24)
at sbt.StandardMain$.runManaged(Main.scala:53)
at sbt.xMain.run(Main.scala:28)
at xsbt.boot.Launch$$anonfun$run.apply(Launch.scala:109)
at xsbt.boot.Launch$.withContextLoader(Launch.scala:128)
at xsbt.boot.Launch$.run(Launch.scala:109)
at xsbt.boot.Launch$$anonfun$apply.apply(Launch.scala:35)
at xsbt.boot.Launch$.launch(Launch.scala:117)
at xsbt.boot.Launch$.apply(Launch.scala:18)
at xsbt.boot.Boot$.runImpl(Boot.scala:41)
at xsbt.boot.Boot$.main(Boot.scala:17)
at xsbt.boot.Boot.main(Boot.scala)
[error] sbt.compiler.EvalException: Type error in expression
[error] Use 'last' for the full log.
Project loading failed: (r)etry, (q)uit, (l)ast, or (i)gnore?
我正在试验游戏框架,对此我还很陌生。提前致谢
- 在 sbt 中只保留一个
build.sbt
文件和一个 project
目录(带有 *.sbt 和 *.scala 配置文件)
- 复制
WebPack.scala
到project
目录。
- 将您的根项目移动到子项目(基础)。
- 重写build.sbt
import play.sbt.PlayImport.PlayKeys.playRunHooks
name := """root"""
version := "1.0-SNAPSHOT"
val scraperDir = "modules/scraper"
val sliderDir = "modules/slider"
lazy val commonSettings = Seq(
scalaVersion := "2.11.7",
libraryDependencies ++= Seq(
jdbc,
cache,
ws,
specs2 % Test
),
resolvers ++= Seq(
"scalaz-bintray" at "http://dl.bintray.com/scalaz/releases"
)
)
lazy val base = projectName("base","base").settings(
playRunHooks += WebPack.apply(file(scraperDir))
)
.dependsOn(scraper,slider)
lazy val scraper = projectName("scraper", scraperDir).settings(
libraryDependencies ++= Seq(
"com.corundumstudio.socketio" % "netty-socketio" % "1.7.8"
),
resolvers ++= Seq(
"Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots")
)
lazy val slider = projectName("slider", sliderDir)
def projectName(name: String, path: String): Project =
Project(name,file(path))
.settings(
commonSettings,
routesGenerator := InjectedRoutesGenerator
)
.enablePlugins(PlayScala)
我们需要一个基础 play 框架项目,其中包含其他 play 和 scala 项目作为模块。这些内部独立的项目可以有不同的 javascript 框架和构建系统,如 webpack、gulp 等
所以我尝试了 https://www.playframework.com/documentation/2.4.x/SBTCookbook 的 PlayRunHook。单个项目挂钩按预期工作。但是,无法在多模块项目上做到正确。一些代码示例...
项目结构
base/build.sbt
name := """base"""
version := "1.0-SNAPSHOT"
lazy val commonSettings = Seq(
scalaVersion := "2.11.6",
libraryDependencies ++= Seq(
jdbc,
cache,
ws,
specs2 % Test
),
resolvers ++= Seq(
"scalaz-bintray" at "http://dl.bintray.com/scalaz/releases"
)
)
lazy val root = (project in file("."))
.settings(commonSettings : _*)
.enablePlugins(PlayScala)
.dependsOn(scraper)
.aggregate(scraper)
.dependsOn(slider)
.aggregate(slider)
lazy val scraper = (project in file("modules/scraper"))
.settings(commonSettings : _*)
.enablePlugins(PlayScala)
lazy val slider = (project in file("modules/slider"))
.settings(commonSettings : _*)
.enablePlugins(PlayScala)
routesGenerator := InjectedRoutesGenerator
base/modules/scraper/build.sbt
import play.sbt.PlayImport.PlayKeys.playRunHooks
import WebPack._
name := """scraper"""
version := "1.0-SNAPSHOT"
lazy val frontendDirectory = baseDirectory {_ / "frontend"}
playRunHooks <+= frontendDirectory.map(WebPack.apply)
routesGenerator := InjectedRoutesGenerator
libraryDependencies ++= Seq(
"com.corundumstudio.socketio" % "netty-socketio" % "1.7.8"
)
resolvers ++= Seq(
"Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"
)
base/modules/slider/build.sbt
name := """slider"""
version := "1.0-SNAPSHOT"
scalaVersion := "2.11.6"
routesGenerator := InjectedRoutesGenerator
base/modules/scraper/project/WebPack.scala
import java.net.InetSocketAddress
import play.sbt.PlayRunHook
import sbt._
object WebPack {
def apply(base: File): PlayRunHook = {
object WebpackHook extends PlayRunHook {
var process: Option[Process] = None
override def beforeStarted(): Unit = {
if (isWindows) {
Process("cmd /c npm run compile", base).run
} else {
Process("npm run compile", base).run
}
}
override def afterStarted(addr: InetSocketAddress): Unit = {
if (isWindows) {
Some(Process("cmd /c npm start", base).run)
} else {
Some(Process("npm start", base).run)
}
}
private def isWindows: Boolean = {
System.getProperty("os.name").startsWith("Windows")
}
override def afterStopped(): Unit = {
process.foreach(_.destroy())
process = None
}
}
WebpackHook
}
}
但是我得到了
...../base/modules/scraper/build.sbt:10: error: not found: object WebPack
import WebPack._
^
sbt.compiler.EvalException: Type error in expression
at sbt.compiler.Eval.checkError(Eval.scala:384)
at sbt.compiler.Eval.compileAndLoad(Eval.scala:183)
at sbt.compiler.Eval.evalCommon(Eval.scala:152)
at sbt.compiler.Eval.evalDefinitions(Eval.scala:122)
at sbt.EvaluateConfigurations$.evaluateDefinitions(EvaluateConfigurations.scala:271)
at sbt.EvaluateConfigurations$.evaluateSbtFile(EvaluateConfigurations.scala:109)
at sbt.Load$.sbt$Load$$loadSettingsFile(Load.scala:712)
at sbt.Load$$anonfun$sbt$Load$$memoLoadSettingsFile.apply(Load.scala:717)
at sbt.Load$$anonfun$sbt$Load$$memoLoadSettingsFile.apply(Load.scala:716)
at scala.collection.MapLike$class.getOrElse(MapLike.scala:128)
at scala.collection.AbstractMap.getOrElse(Map.scala:58)
at sbt.Load$.sbt$Load$$memoLoadSettingsFile(Load.scala:716)
at sbt.Load$$anonfun$loadFiles.apply(Load.scala:723)
at sbt.Load$$anonfun$loadFiles.apply(Load.scala:723)
at scala.collection.TraversableLike$$anonfun$map.apply(TraversableLike.scala:244)
at scala.collection.TraversableLike$$anonfun$map.apply(TraversableLike.scala:244)
at scala.collection.immutable.List.foreach(List.scala:318)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
at scala.collection.AbstractTraversable.map(Traversable.scala:105)
at sbt.Load$.loadFiles(Load.scala:723)
at sbt.Load$.discoverProjects(Load.scala:734)
at sbt.Load$.discover(Load.scala:545)
at sbt.Load$.discoverAndLoad(Load.scala:554)
at sbt.Load$.loadTransitive(Load.scala:570)
at sbt.Load$.loadProjects(Load.scala:442)
at sbt.Load$.loadUnit(Load.scala:446)
at sbt.Load$$anonfun$$anonfun$apply.apply(Load.scala:281)
at sbt.Load$$anonfun$$anonfun$apply.apply(Load.scala:281)
at sbt.BuildLoader$$anonfun$componentLoader$$anonfun$apply$$anonfun$apply$$anonfun$apply.apply(BuildLoader.scala:91)
at sbt.BuildLoader$$anonfun$componentLoader$$anonfun$apply$$anonfun$apply$$anonfun$apply.apply(BuildLoader.scala:90)
at sbt.BuildLoader.apply(BuildLoader.scala:140)
at sbt.Load$.loadAll(Load.scala:334)
at sbt.Load$.loadURI(Load.scala:289)
at sbt.Load$.load(Load.scala:285)
at sbt.Load$.load(Load.scala:276)
at sbt.Load$.apply(Load.scala:130)
at sbt.Load$.defaultLoad(Load.scala:36)
at sbt.BuiltinCommands$.doLoadProject(Main.scala:481)
at sbt.BuiltinCommands$$anonfun$loadProjectImpl.apply(Main.scala:475)
at sbt.BuiltinCommands$$anonfun$loadProjectImpl.apply(Main.scala:475)
at sbt.Command$$anonfun$applyEffect$$anonfun$apply.apply(Command.scala:58)
at sbt.Command$$anonfun$applyEffect$$anonfun$apply.apply(Command.scala:58)
at sbt.Command$$anonfun$applyEffect$$anonfun$apply.apply(Command.scala:60)
at sbt.Command$$anonfun$applyEffect$$anonfun$apply.apply(Command.scala:60)
at sbt.Command$.process(Command.scala:92)
at sbt.MainLoop$$anonfun$$anonfun$apply.apply(MainLoop.scala:98)
at sbt.MainLoop$$anonfun$$anonfun$apply.apply(MainLoop.scala:98)
at sbt.State$$anon.process(State.scala:184)
at sbt.MainLoop$$anonfun.apply(MainLoop.scala:98)
at sbt.MainLoop$$anonfun.apply(MainLoop.scala:98)
at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17)
at sbt.MainLoop$.next(MainLoop.scala:98)
at sbt.MainLoop$.run(MainLoop.scala:91)
at sbt.MainLoop$$anonfun$runWithNewLog.apply(MainLoop.scala:70)
at sbt.MainLoop$$anonfun$runWithNewLog.apply(MainLoop.scala:65)
at sbt.Using.apply(Using.scala:24)
at sbt.MainLoop$.runWithNewLog(MainLoop.scala:65)
at sbt.MainLoop$.runAndClearLast(MainLoop.scala:48)
at sbt.MainLoop$.runLoggedLoop(MainLoop.scala:32)
at sbt.MainLoop$.runLogged(MainLoop.scala:24)
at sbt.StandardMain$.runManaged(Main.scala:53)
at sbt.xMain.run(Main.scala:28)
at xsbt.boot.Launch$$anonfun$run.apply(Launch.scala:109)
at xsbt.boot.Launch$.withContextLoader(Launch.scala:128)
at xsbt.boot.Launch$.run(Launch.scala:109)
at xsbt.boot.Launch$$anonfun$apply.apply(Launch.scala:35)
at xsbt.boot.Launch$.launch(Launch.scala:117)
at xsbt.boot.Launch$.apply(Launch.scala:18)
at xsbt.boot.Boot$.runImpl(Boot.scala:41)
at xsbt.boot.Boot$.main(Boot.scala:17)
at xsbt.boot.Boot.main(Boot.scala)
[error] sbt.compiler.EvalException: Type error in expression
[error] Use 'last' for the full log.
Project loading failed: (r)etry, (q)uit, (l)ast, or (i)gnore?
我正在试验游戏框架,对此我还很陌生。提前致谢
- 在 sbt 中只保留一个
build.sbt
文件和一个project
目录(带有 *.sbt 和 *.scala 配置文件) - 复制
WebPack.scala
到project
目录。 - 将您的根项目移动到子项目(基础)。
- 重写build.sbt
import play.sbt.PlayImport.PlayKeys.playRunHooks
name := """root"""
version := "1.0-SNAPSHOT"
val scraperDir = "modules/scraper"
val sliderDir = "modules/slider"
lazy val commonSettings = Seq(
scalaVersion := "2.11.7",
libraryDependencies ++= Seq(
jdbc,
cache,
ws,
specs2 % Test
),
resolvers ++= Seq(
"scalaz-bintray" at "http://dl.bintray.com/scalaz/releases"
)
)
lazy val base = projectName("base","base").settings(
playRunHooks += WebPack.apply(file(scraperDir))
)
.dependsOn(scraper,slider)
lazy val scraper = projectName("scraper", scraperDir).settings(
libraryDependencies ++= Seq(
"com.corundumstudio.socketio" % "netty-socketio" % "1.7.8"
),
resolvers ++= Seq(
"Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots")
)
lazy val slider = projectName("slider", sliderDir)
def projectName(name: String, path: String): Project =
Project(name,file(path))
.settings(
commonSettings,
routesGenerator := InjectedRoutesGenerator
)
.enablePlugins(PlayScala)