Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I run webpack from SBT

I'm developing a Play 2.4 application and would like SBT to run webpack to generate static assets during compilation.

I tried https://github.com/stejskal/sbt-webpack but it does't seem to work for me.

like image 243
Andrey Cheptsov Avatar asked Jan 02 '16 16:01

Andrey Cheptsov


3 Answers

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 Webpackdefined 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 ;-)

like image 68
Nouhoum TRAORE Avatar answered Nov 10 '22 15:11

Nouhoum TRAORE


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
like image 33
Bruno Paulino Avatar answered Nov 10 '22 16:11

Bruno Paulino


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

like image 2
Tanin Avatar answered Nov 10 '22 15:11

Tanin