简体   繁体   中英

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.

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM