How do I run webpack from SBT
Nouhoum's answer was working fine until I updated to SBT 1.0.x
Just a few updates were needed:
import scala.sys.process.Process
lazy val webpack = taskKey[Unit]("Run webpack when packaging the application")
def runWebpack(file: File) = {
Process("npm run build", file) !
}
webpack := {
if(runWebpack(baseDirectory.value) != 0) throw new Exception("Something went wrong when running webpack.")
}
dist := (dist dependsOn webpack).value
stage := (stage dependsOn webpack).value
We've built sbt-webpack
that integrates cleanly with the incremental compilation with Playframework's static assets. I hope that what you want. It works as expected with sbt run
and sbt stage
.
At GIVE.asia, We are using it for packaging Vue
, Axios
, and Vue-i18
into a single JS file, which is later included in our HTML file. Then, we use expose-loader
to expose the variables Vue
, VueI18n
, and axios
.
The reason to prefer sbt-webpack
is that it generates the output file to an appropriate location that can be used by Playframework's routing. Because it integrates with the incremental compilation with Playframework's static assets.
Here's the repo: https://github.com/GIVESocialMovement/sbt-webpack
Or you can jump directly to a working example: https://github.com/GIVESocialMovement/sbt-webpack/tree/master/test-play-project
I managed to have it work by defining a custom sbt task that is used a dependence for dist
and stage
tasks invoked when you package your application.
The code of the task is straight forward :
lazy val webpack = taskKey[Unit]("Run webpack when packaging the application")
def runWebpack(file: File) = {
Process("webpack", file) !
}
webpack := {
if(runWebpack(baseDirectory.value) != 0) throw new Exception("Something goes wrong when running webpack.")
}
dist <<= dist dependsOn webpack
stage <<= stage dependsOn webpack
In dev mode I use play action hooks to run webpack watch
when the code changes :
PlayKeys.playRunHooks <+= baseDirectory.map(Webpack.apply)
with Webpack
defined as follows :
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() = {
process = Option(
Process("webpack", base).run()
)
}
override def afterStarted(addr: InetSocketAddress) = {
process = Option(
Process("webpack --watch", base).run()
)
}
override def afterStopped() = {
process.foreach(_.destroy())
process = None
}
}
WebpackHook
}
}
It works like a charm. You find at my github account a sample play project using this technique : https://github.com/nouhoum/play-react-webpack/blob/master/webpack.sbt
I hope this helps ;-)