I have two separated git repos, one holds a scala server built with sbt, the other holds a webapp frontend built with npm/bower/gulp.
In server repo, I already have a task to build a standalone jar (not the standard package task) ; in frontend repo, I can build with npm install && npm run build
which would result into a standalone directory _public
.
Now I would like to include the UI directory _public
during sbt building jar task, I am wondering if there is a better way to do so other than manually spawn external process in sbt to call npm ?
The current state of sbt-web and webjars relying on it is that they are hardly keeping up with the growth of Node.js and npm. For example, the sbt-hbs
plugin is no longer maintained, and my experience shows that it won't work with any Node.js version 8 or above. Support for sbt 1.0 is also not complete in some of these webjar-based frontent tools.
As such, unlike what the question suggests, directly spawning npm processes via sbt to build the frontend is a better solution than many.
This answer from a different question provides a sufficiently reliable way to call npm from sbt, which I will only replicate here for completeness.
buildFrontend := {
val s: TaskStreams = streams.value
val shell: Seq[String] = if (sys.props("os.name").contains("Windows")) Seq("cmd", "/c") else Seq("bash", "-c")
val npmInstall: Seq[String] = shell :+ "npm install"
val npmTest: Seq[String] = shell :+ "npm run test"
val npmLint: Seq[String] = shell :+ "npm run lint"
val npmBuild: Seq[String] = shell :+ "npm run build"
s.log.info("building frontend...")
if((npmInstall #&& npmTest #&& npmLint #&& npmBuild !) == 0) {
s.log.success("frontend build successful!")
} else {
throw new IllegalStateException("frontend build failed!")
}
}
If your frontend uses NPM and Gulp to build the app, you need to run it with a NodeJS engine (or maybe JVM engines like Rhino or Nashorn can do it? not sure) and it requires an external process.
The question to ask yourself is: do you really want to couple the deployment of your backend from the deployment of your frontend? Isn't there any case where you simply want to deploy one and not the other?
I think using SBT to deploy you frontend is nice but if your frontend is complex, you'd rather keep it separate from SBT.
Your JS app does not necessarily need to be served as a Play public asset, you could simply deploy it to its own place and reference it inside a Play HTML template.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With