JMC
JMC

Reputation: 393

how to minify js produced by sbt-concat

I was doing my experiments using sbt-concat to combine css/js bundles. I then tried to expand my pipeline in order to do minify for my css and js. It is fairly easy to use sbt-css-compress which does minification of all the CSS produced by sbt-concat. I tried sbt-closure for js, but it does not seem to work. Just to be clear, I tried sbt-closure and it is confirmed that it does compilation of all js below to /assets. However I am trying to figure out if it works with sbt-concat.

For example: if I have /assets/js/f1.js and /assets/js/f2.js and I would like to combine them and minify into 1 bundle file.

Upvotes: 2

Views: 1856

Answers (3)

Jiro Matchonson
Jiro Matchonson

Reputation: 981

This is just a bit edited Yoel Garcia answer specifically for play 2.3, give him a thumb up :-)

Play 2.3 Plugins.sbt

addSbtPlugin("net.ground5hark.sbt" % "sbt-concat" % "0.1.9")
addSbtPlugin("net.ground5hark.sbt" % "sbt-closure" % "0.1.3")

build.sbt

lazy val root = (project in file(".")).enablePlugins(SbtWeb)
//if already use some just separate enablePlugins(Play, JavaAppPackaging, SbtWeb)

resolvers += Resolver.sonatypeRepo("releases") //You probably have already this

Concat.groups := Seq(
  "all2.js" -> group(Seq(
    "lib/jquery/jquery.min.js",
    "lib/react/react-with-addons.js"
  ))
)

Concat.parentDir := "concated"
Closure.suffix := ".min.js"
Closure.parentDir := "concated"
Closure.flags := Seq("--formatting=PRETTY_PRINT", "--accept_const_keyword")
includeFilter in closure := "all2.js"
pipelineStages in Assets := Seq(concat, closure, digest)

//all need to run in pipelineStages in Assets, otherwise You see nothing in develop, You can switch to pipelineStages := Seq(concat, closure, digest) later probably, that runs only in production build

Then in layout.scala You can test it

<script type="text/javascript" src="@controllers.routes.Assets.at("concated/all2.min.js")"></script>

For final version You probably want switcher depending on dev/build mode

     @if(play.api.Play.current.mode == play.api.Mode.Prod) {
            <script type="text/javascript" src="@controllers.routes.Assets.at("concated/all2.min.js")"></script>
        } else {
            <script type="text/javascript" src="@controllers.routes.Assets.at("lib/jquery/jquery.min.js")"></script>
            <script type="text/javascript" src="@controllers.routes.Assets.at("lib/react/react-with-addons.js")"></script>
//And all other scripts, You do not want to debug in minified scripts
        }

Upvotes: 0

dwickern
dwickern

Reputation: 3519

You can use sbt-uglify to combine and minify.

Add to plugins.sbt:

addSbtPlugin("com.typesafe.sbt" % "sbt-uglify" % "1.0.3")

Add to build.sbt:

pipelineStages := Seq(uglify)

UglifyKeys.uglifyOps := { js =>
  Seq((js.sortBy(_._2), "main.min.js"))
}

This will combine your javascript sources alphabetically by their file path.

Use pipelineStages in Assets if you want to concat/uglify in development. Normally it would only execute for a production build.

Upvotes: 5

Yoel Garcia
Yoel Garcia

Reputation: 173

One way that I know is to do the concat in 'pipelineStages in Assests' and include a filter

For example in build.sbt

Concat.groups := Seq(
  "all.js" -> group(Seq(
    "js/f1.js",
    "js/f2.js"
  ))
)

Concat.parentDir := "concated"

Closure.suffix := ".min.js"

Closure.flags := Seq("--formatting=PRETTY_PRINT", "--accept_const_keyword")

pipelineStages in Assets := Seq(concat)

includeFilter in closure := "all.js"

pipelineStages := Seq(closure, digest, gzip)

Upvotes: 3

Related Questions