Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to integrate npm/gulp/bower building process into sbt?

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 ?

like image 200
Chikei Avatar asked Nov 28 '14 09:11

Chikei


2 Answers

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!")
  }
}
like image 168
E_net4 stands with Ukraine Avatar answered Nov 15 '22 22:11

E_net4 stands with Ukraine


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.

like image 21
Sebastien Lorber Avatar answered Nov 15 '22 23:11

Sebastien Lorber