fastOptJS
to the correct location in that directory
lazy val myNWjs = project.settings(
scalaJSProjects := Seq(client),
pipelineStages in Assets := Seq(scalaJSPipeline)
).enablePlugins(SbtWeb)
lazy val client = project.enablePlugins(ScalaJSPlugin, ScalaJSWeb)
watchSources ++= ((Compile / sourceDirectory).value / "assets" ** "*").get
val fastStage = taskKey[Unit]("Copy all to staging dir")
val fullStage = taskKey[Unit]("Copy all to staging dir")
def performStage(optJS: TaskKey[Attributed[File]]) = Def.task {
val tgtPublicDir = (Assets / public).value
(Assets / assets).value
val jsDir = tgtPublicDir / "js"
if (!jsDir.exists) IO.createDirectory(jsDir)
val tgtFile = jsDir / s"${name.value}.js"
val jsFile = (Compile / optJS).value.data
IO.copyFile(jsFile, tgtFile)
}
fastStage := performStage(fastOptJS).value
fullStage := performStage(fullOptJS).value
assets
if added after I did ~fastStage
sbt-web-scalajs will only work if you have separate projects because you need to set the scalaJSProjects
setting and you can't self reference your only project. This won't work:
val client = project.settings(
scalaJSProjects := Seq(client), ...
).enablePlugins(SbtWeb)
If you only need to copy fastOptJS output to another directory, it's probably not worth using sbt-web-scalajs in your case.
run
/compile
the server project?server/target/<etc>
after compilation.name := "test"
val commonSettings = Seq(
scalaVersion := "2.12.4",
version := "1.0"
)
val http4s = "0.18.0-M9"
lazy val server = (project in file("server"))
.enablePlugins(SbtWeb)
.settings(commonSettings)
.settings(
scalacOptions ++= Seq("-Ypartial-unification"),
libraryDependencies ++= Seq(
"org.http4s" %% "http4s-dsl" % http4s,
"org.http4s" %% "http4s-blaze-server" % http4s,
"org.http4s" %% "http4s-circe" % http4s,
"ch.qos.logback" % "logback-classic" % "1.2.3",
"com.typesafe.scala-logging" %% "scala-logging" % "3.7.2"
),
scalaJSProjects := Seq(client),
pipelineStages in Assets := Seq(scalaJSPipeline),
compile in Compile := ((compile in Compile) dependsOn scalaJSPipeline).value
/*resourceGenerators in Compile += Def.task {
println("Copying ScalaJS sources...")
val files = ((crossTarget in(client, Compile)).value ** ("*.js" || "*.map")).get
val mappings: Seq[(File,String)] = files pair Path.rebase(
(crossTarget in(client, Compile)).value,
((resourceManaged in Compile).value / "web/js/").getAbsolutePath
)
val map: Seq[(File, File)] = mappings.map { case (s, t) => (s, file(t))}
IO.copy(map).toSeq
} dependsOn (fastOptJS in(client, Compile))*/
)
lazy val client = (project in file("client"))
.enablePlugins(ScalaJSPlugin, ScalaJSWeb)
.settings(commonSettings)
.settings(
scalaJSUseMainModuleInitializer := true,
libraryDependencies ++= Seq(
"be.doeraene" %%% "scalajs-jquery" % "0.9.1",
"com.lihaoyi" %%% "scalatags" % "0.6.7",
"com.lihaoyi" %%% "scalarx" % "0.3.2",
"com.timushev" %%% "scalatags-rx" % "0.3.0"
),
skip in packageJSDependencies := false,
jsDependencies ++= Seq(
"org.webjars" % "jquery" % "2.1.4" / "2.1.4/jquery.js",
)
)
// loads the server project at sbt startup
onLoad in Global := (onLoad in Global).value andThen {s: State => "project server" :: s}
~run
on my server project, nothing happens when the client sources change.
~reStart
) with akka-http if you want to see your changes get automatically included. Unfortunately, it restarts the web server, which can be slow, but I don't know any way around it. The experience is a bit better with Play framework: the server does not need to be restarted when an asset file (HTML/CSS, JS, etc.) gets modified but Play has its own auto-reload feature.
compile in Compile := ((compile in Compile) dependsOn scalaJSPipeline).value
to you server's settings. Have a look at https://github.com/vmunier/akka-http-scalajs.g8 for an example (sbt new vmunier/akka-http-scalajs.g8)
import cats.effect.Sync
import java.io.File
import org.http4s.{ HttpService, Request, Response, StaticFile }
import org.http4s.dsl.Http4sDsl
import org.http4s.dsl.io._
import org.http4s.twirl._
import app.html
class SpaController[F[_]: Sync] extends Http4sDsl[F] {
val service: HttpService[F] = HttpService[F] {
case GET -> Root => Ok(
html.index("App title")
)
case request @ GET -> "assets" /: rest =>
static(rest, request)
}
private def static(path: Path, request: Request[F]): F[Response[F]] =
StaticFile.fromResource(s"public/$path", Some(request)).getOrElseF(NotFound())
}
lazy val shared = commonSettings ++ Seq(
name := "intranet-shared",
libraryDependencies ++= Dependencies.shared.value,
)
lazy val server = commonSettings ++ Seq(
name := "intranet-server",
libraryDependencies ++= Dependencies.server,
libraryDependencies ++= Dependencies.jvm,
pipelineStages in Assets := Seq(scalaJSPipeline),
compile in Compile := ((compile in Compile) dependsOn scalaJSPipeline).value,
WebKeys.packagePrefix in Assets := "public/",
managedClasspath in Runtime += (packageBin in Assets).value,
)
lazy val client = commonSettings ++ Seq(
name := "intranet-client",
mainClass in Compile := Some("app.Application"),
libraryDependencies ++= Dependencies.client.value,
npmDependencies in Compile := Dependencies.js,
npmDevDependencies in Compile := Dependencies.devJs,
webpackConfigFile in fastOptJS := Some(baseDirectory.value / "dev.webpack.config.js"),
webpackConfigFile in fullOptJS := Some(baseDirectory.value / "prod.webpack.config.js"),
scalaJSUseMainModuleInitializer := true,
scalaJSUseMainModuleInitializer in Test := false,
jsEnv := new org.scalajs.jsenv.jsdomnodejs.JSDOMNodeJSEnv,
webpackBundlingMode := BundlingMode.LibraryOnly(),
)
build.sbt
lazy val shared = crossProject(JSPlatform, JVMPlatform)
.crossType(CrossType.Pure)
.in(file("shared"))
.settings(BuildSettings.shared)
.jsConfigure(_.enablePlugins(ScalaJSWeb, ScalaJSBundlerPlugin))
lazy val sharedJVM = shared.jvm.settings(name := "sharedJVM")
lazy val sharedJS = shared.js.settings(name := "sharedJS")
lazy val server = project
.in(file("server"))
.settings(BuildSettings.server)
.settings(scalaJSProjects := Seq(client))
.enablePlugins(WebScalaJSBundlerPlugin, SbtTwirl, JavaAppPackaging)
.aggregate(client)
.dependsOn(sharedJVM)
lazy val client: Project = project
.in(file("client"))
.settings(BuildSettings.client)
.enablePlugins(ScalaJSPlugin, ScalaJSBundlerPlugin, ScalaJSWeb)
.dependsOn(sharedJS)
onLoad in Global := (onLoad in Global).value andThen {s: State => "project server" :: s}
import java.nio.file.{Files, StandardCopyOption}
import com.typesafe.sbt.packager.SettingsHelper._
lazy val server = project
.in(file("server"))
.settings(BuildSettings.server)
.settings(
scalaJSProjects := Seq(client),
(Compile / resourceGenerators) += Def.task {
val webpackFiles = (client / Compile / fullOptJS / webpack).value.map(_.data).filterNot(_.getName contains "bundle")
val npmFiles = Seq.empty[File]
(webpackFiles ++ npmFiles).map { sourceFile =>
val targetFile = (Compile / resourceManaged).value / "public" / sourceFile.getName
Files.createDirectories(targetFile.getParentFile().toPath())
Files.copy(sourceFile.toPath, targetFile.toPath, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES)
targetFile
}
}.taskValue,
)
.enablePlugins(WebScalaJSBundlerPlugin, SbtTwirl, JavaAppPackaging)
.aggregate(client)
.dependsOn(sharedJVM)
show compile:managedResources
[info] client / Compile / managedResources
[info] List()
[info] Compile / managedResources
[info] List(/home/user/Projects/intranet/server/target/scala-2.12/resource_managed/main/public/intranet-client-opt.js, /home/user/Projects/intranet/server/target/scala-2.12/resource_managed/main/public/intranet-client-opt-loader.js, /home/user/Projects/intranet/server/target/scala-2.12/resource_managed/main/public/intranet-client-opt-library.js, /home/user/Projects/intranet/server/target/scala-2.12/resource_managed/main/public/intranet-client-opt-library.js.map)
~run
and ~reStart
but if I change the SharedMessages.itWorks content, and refresh the page, it doesn't show the update message unless I ctrl + c and re-run it.