How to enable minified JavaScript files in Play 2.3.1 templates?

I was able to load the sbt-uglify 1.0.3 plugin in my Play Framework 2.3.1 app. Loading of the non-minified javascripts is pretty straightforward, but loading the minified versions seems to be impossible.

In my template I use <script> tags similar to this:

<script src="@routes.Assets.at("javascripts/app.js")"></script>

In dev mode, the non-minified javascript version is loaded, which is fine. In prod mode (using activator start) I see sbt-uglify generating the minified versions to the target/web/uglify/build folder, but because I didn't change the above <script> tag line in my templates, the non-minified versions of the javascripts files are loaded.

Is there a way to do a prod-only mapping of such routes to load the minified versions?

Answers


The issue Reverse Router should use minified assets in production automatically was fixed in Play 2.3.1 that exactly matches your requirement.

According to Play 2.3.1 Changelog:

The behaviour of the Assets reverse router has changed, if minified versions of assets exist, it now returns a URL for those instead. To disable this behaviour, set assets.checkForMinified=true in application.conf.

NOTE It should rather read set assets.checkForMinified=false, but anyway...

What follows works in production mode only so start the application with activator start not run or use the generated start scripts (after stage).

The behaviour of using minified versions of assets in production should be enabled by default in the version of Play with @routes.Assets.versioned (not routes.Assets.at).

It does require that the appropriate route declaration in conf/routes is:

GET  /assets/*file  controllers.Assets.versioned(path="/public", file: Asset)

What I found a bit unclear at first was the order of elements in pipelineStages as well as the requirement to include sbt-rjs in it.

And just after I'd written the sentence about the order I found in the section "RequireJS" in Play 2.3 Migration Guide:

The order of stages is significant. You first want to optimize the files, produce digests of them and then produce gzip versions of all resultant assets.

I've also found in Play 2.3 Migration Guide in the section "Closure Compiler":

UglifyJS 2 is presently provided via the RequireJS plugin (described next). The intent in future is to provide a standalone UglifyJS 2 plugin also for situations where RequireJS is not used.

It all started with the answer to Play 2.3 sbt-web plugin Javascript minification.

So, the below pipelineStages is the working one - mind the order and rjs:

pipelineStages := Seq(rjs, uglify, digest, gzip)

project/plugins.sbt used was as follows:

resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"

addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.5")

addSbtPlugin("com.typesafe.sbt" % "sbt-digest" % "1.0.0")

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

addSbtPlugin("com.typesafe.sbt" % "sbt-gzip" % "1.0.0")

addSbtPlugin("com.typesafe.sbt" % "sbt-rjs" % "1.0.6")

Don't forget to create an empty app/assets/javascripts/main.js file to let sbt-rjs do its job.

As a test, I created a Play application with activator new playApp play-scala and applied the above changes in the build as well as in app/views/main.scala.html that ultimately looked as follows (note @routes.Assets.versioned):

@(title: String)(content: Html)

<!DOCTYPE html>

<html>
    <head>
        <title>@title</title>
        <link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/main.css")">
        <link rel="shortcut icon" type="image/png" href="@routes.Assets.versioned("images/favicon.png")">
        <script src="@routes.Assets.versioned("javascripts/hello.js")" type="text/javascript"></script>
    </head>
    <body>
        @content
    </body>
</html>

Executing activator start and calling curl http://localhost:9000 gives (formatting's mine for the sake of readability):

➜  play-uglify  curl http://localhost:9000

<!DOCTYPE html>

<html>
    <head>
        <title>Welcome to Play</title>
        <link rel="stylesheet" media="screen" href="/assets/stylesheets/d41d8cd98f00b204e9800998ecf8427e-main.css">
        <link rel="shortcut icon" type="image/png" href="/assets/images/84a01dc6c53f0d2a58a2f7ff9e17a294-favicon.png">
        <script src="/assets/javascripts/4302136334616ae0605d47a1932ee262-hello.min.js" type="text/javascript"></script>
    </head>
    <body>
        <h1>Your new application is ready.</h1>
    </body>
</html>

Note 4302136334616ae0605d47a1932ee262-hello.min.js and the non-JavaScript resources digested.


Need Your Help

Why does running this query with EXECUTE IMMEDIATE cause it to fail?

sql oracle plsql dynamic-sql ora-00911

I am writing a PL/SQL procedure that needs to to dynamically generate some queries, one of which involves creating a temporary table using results from a query taken as a parameter.