Play 2.3 sbt-web plugin Javascript minification

2,268 views
Skip to first unread message

Keuller Magalhaes

unread,
Jun 9, 2014, 5:51:58 PM6/9/14
to play-fr...@googlegroups.com
Hi Guys,

In Play 2.2 Javascript minification was automatically, but Play 2.3 introduces a new Sbt-Web plugin thats allow us to customize some assets actions.

But I'm trying to figure out how can I minify my Javascripts assets. I put my JS files into app/assets/js folder. Below is code snippet from build.sbt file

lazy val root = project.in(file("."))
    .enablePlugins(PlayJava, SbtWeb)

pipelineStages := Seq(rjs, gzip)

The content from plugins.sbt file is like:

// Use the Play sbt plugin for Play projects
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.0")

addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.5.0")

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

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

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

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

Anyone could help to solve that ?

Regards.

Timo Hirt

unread,
Jun 10, 2014, 4:28:30 AM6/10/14
to play-fr...@googlegroups.com
Assuming you have RequireJS in plance, take a look at the sbt-rjs README on github (https://github.com/sbt/sbt-rjs). Does your Javascript match the default configuration.If you don`t have a main.js then set a main module (eg. RjsKeys.mainModule := "app") that fits you application.

Keuller Magalhaes

unread,
Jun 10, 2014, 8:43:35 AM6/10/14
to play-fr...@googlegroups.com
Hi Timo, 

I see it, but what I realized for that is I need to use (or forced to use) RequireJS always for minification ? I dont want to use RequireJS to manager my JS files, I just want minify them. If is not possible I think it is a lack of sbt-web plugin, besides Play 2.2 had this features automatically.

Regards.

Megazord

unread,
Jun 11, 2014, 10:39:29 AM6/11/14
to play-fr...@googlegroups.com
It is also possible to minify assets in play 2.3.0 "without" requirejs configuration. Just add a app/assets/javascripts/main.js file with a comment like this:

// nothing to see

After that, just reference your JavaScript files without the "min" section like this:

@routes.Assets.versioned("javascripts/users.js")


At least this trick had worked for me. :-)

HTH

Mike Bryant

unread,
Jun 11, 2014, 1:13:38 PM6/11/14
to play-fr...@googlegroups.com
Great tip! This actually works for me, with caveats. 

Next problem (without wanting to hijack this thread): if I try and use this minimal sbt-rjs setup in a multi-module build I end up with the following error:

java.util.zip.ZipException: duplicate entry: public/build.txt
at java.util.zip.ZipOutputStream.putNextEntry(ZipOutputStream.java:175)
at java.util.jar.JarOutputStream.putNextEntry(JarOutputStream.java:92)
at sbt.IO$.sbt$IO$$addFileEntry$1(IO.scala:445)
at sbt.IO$$anonfun$sbt$IO$$writeZip$2.apply(IO.scala:454)
at sbt.IO$$anonfun$sbt$IO$$writeZip$2.apply(IO.scala:454)
...

as far as I can see this "build.txt" file is hard-coded in requirejs. Anyone know of a way to stop multiple modules interfering with each other here?

~Mike

Megazord

unread,
Jun 11, 2014, 6:48:01 PM6/11/14
to play-fr...@googlegroups.com
Hum... since I'm using nginx, I don't use gzip in the assets pipeline. But this sounds like a bug to me. Do you mind to open a issue here?

https://github.com/sbt/sbt-gzip

Or maybe here?

https://github.com/sbt/sbt-web

Not sure how play team is handling issues between these different projects.

HTH

Mike Bryant

unread,
Jun 12, 2014, 4:29:33 AM6/12/14
to play-fr...@googlegroups.com
It seems to happen whether or not gzip is in the pipeline (or digest for that matter), presumably when the assets jar is pacakged. I'll try and reproduce it in a minimal sub-project app and if necessary follow up with an issue.

Thanks for your help,
~Mike 

Christopher Hunt

unread,
Jun 15, 2014, 12:28:07 AM6/15/14
to play-fr...@googlegroups.com
Some good news. I've now created and published sbt-uglify so that you can minify etc without needing rjs.

In Play 2.3.0 you need then to reference the .min qualified file when in prod mode. However in 2.3.1 the reverse router will automatically check for the presence of minified files so that your source html does not change.

HTH

Christopher Hunt

unread,
Jun 15, 2014, 12:29:15 AM6/15/14
to play-fr...@googlegroups.com

Rodrigo Fernandes

unread,
Jun 17, 2014, 12:29:57 PM6/17/14
to play-fr...@googlegroups.com
Hi,
I have a structure like play 2.2 and i basically have my js in:
`app/assets/javascripts` and some of them inside other folder.

How can I have the same type of minification i had in play 2.2?

Christopher Hunt

unread,
Jun 17, 2014, 12:36:05 PM6/17/14
to play-fr...@googlegroups.com
You should be able to use sbt-uglify here or sbt-rjs; the latter in case you're using RequireJS.

--
You received this message because you are subscribed to a topic in the Google Groups "play-framework" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/play-framework/VQv_tjngCpM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to play-framewor...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


-- 
Christopher Hunt
Senior Engineer
Typesafe – Build Reactive Apps on the JVM!

Twitter: @huntchr

Rodrigo Fernandes

unread,
Jun 17, 2014, 12:46:40 PM6/17/14
to play-fr...@googlegroups.com
Hi Christopher,

We are not currently using requirejs and since that would take a lot of work we want to maintain the latest solution.
Can I have the same minification I had in play 2.2?

Christopher Hunt

unread,
Jun 18, 2014, 1:50:12 AM6/18/14
to play-fr...@googlegroups.com

On 17/06/2014, at 6:46 PM, Rodrigo Fernandes <rtfro...@gmail.com> wrote:

We are not currently using requirejs and since that would take a lot of work we want to maintain the latest solution.
Can I have the same minification I had in play 2.2?
What was minified and concatenated for your previous project?

Rodrigo Fernandes

unread,
Jun 18, 2014, 4:18:41 AM6/18/14
to play-fr...@googlegroups.com
In our project we have a distribution of folders like:

  • app
    • assets
      • javascripts
        • project
          • detail.js
          • ....
        • template.js
        • ....
In the html we just import each file we need.
And with this structure the files would be minified and available in the assets with that same structure.
We tried rjs but it seems to need the main entry point we don't have.
And we tried sbt-uglify and we set it's folder to "app/assets", in the end what it did was destroy the *.js files and create folders (was it suposed to work, what to we need to specify in the properties?)

Is it possible to have same structure as before?

Megazord

unread,
Jun 18, 2014, 3:25:02 PM6/18/14
to play-fr...@googlegroups.com
Rodrigo,

What do you mean by "destroy the js files"? It corrupt them while minifying? How is sbt-uglify configured?

Best,

Rodrigo Fernandes

unread,
Jun 18, 2014, 3:45:55 PM6/18/14
to play-fr...@googlegroups.com
The only configuration from sbt-uglify I set was the "buildDir" and I
put "app/assets". Still i did not understood much from the
documentation in the page. The documentation is very much driven to
the requirejs. Since I do not have the requirejs structure I just want
you to help me in how can I setup my build.sbt file to have exactly
the same I had on play 2.2.

Can you explain what are the configs I need to set and the to import
to have the same as in play 2.2?
Best Regards,
Rodrigo Fernandes
>>> Typesafe - Build Reactive Apps on the JVM!
>>>
>>> Twitter: @huntchr
>>>

Megazord

unread,
Jun 18, 2014, 5:26:11 PM6/18/14
to play-fr...@googlegroups.com
I didn't found buildDir configuration in the docs:

https://github.com/sbt/sbt-uglify/blob/master/README.md
http://lisperator.net/uglifyjs/

Where did you saw it?

Anyway, here is what you could do to have play 2.2.x behavior while using play 2.3.x:

1. Turn on rjs in your pipelineStages
2. Create an empty file in app/assets/javascripts/main.js
3. Remove ".min" section when referencing files inside views
4. Tada!

HTH

Christopher Hunt

unread,
Jun 20, 2014, 7:02:05 AM6/20/14
to play-fr...@googlegroups.com
Can you please raise an issue on sbt-uglify so that there's the option to minify files individually?

Rodrigo Fernandes

unread,
Jun 21, 2014, 3:02:50 AM6/21/14
to play-fr...@googlegroups.com
Hi Megazord,

If I understood what you are saying is that if I remove the .min the
files will be minified?
And I can keep including them individually without requirejs?

Best Regards,
Rodrigo Fernandes

Rodrigo Fernandes

unread,
Jun 21, 2014, 3:42:41 AM6/21/14
to play-fr...@googlegroups.com
Hi Megazord,

That is not working. It is not minifying any files.
Best Regards,
Rodrigo Fernandes

Megazord

unread,
Jun 21, 2014, 3:52:33 AM6/21/14
to play-fr...@googlegroups.com
Rodrigo,

Pay attention to the following facts:

1. You need to add an app/assets/javascript/main.js file, even if it is empty (mine just has a comment explaining why the file exists)
2. You need to add rjs to your pipelineStages. Just follow the steps documented in the plugin repository[1]
3. We are talking just about js files, since less/css files are compressed by sbt-less[2]

How are you trying right now?

[1] https://github.com/sbt/sbt-rjs
[2] https://github.com/sbt/sbt-less

Rodrigo Fernandes

unread,
Jun 21, 2014, 4:29:39 AM6/21/14
to play-fr...@googlegroups.com
Megazord,

About the LESS, my less files are being minifyed very well.

About the JS, I did all that you said but I have some questions:
Does the file need to be in the folder `app/assets/javascript` or in
my folder that is `app/assets/javascripts`?
The js files are copied but always play text.
Anyway it seems to not work with either. Do I need any other config?
Best Regards,
Rodrigo Fernandes

Megazord

unread,
Jun 21, 2014, 3:30:34 PM6/21/14
to play-fr...@googlegroups.com
Well,

Could you please send more details about what you tried and how your configuration is right now?

1. Which version of sbt-rjs plugin?
2. What is the output when running "activator start"?
3. How did you have configured pipelineStages?

Moreover, as far as I know, js files are not minified when you running in development mode (activator run).

HTH

Rodrigo Fernandes

unread,
Jun 21, 2014, 4:24:49 PM6/21/14
to play-fr...@googlegroups.com
Megazord,

My config is just like this:
unmanagedResourceDirectories in Assets += baseDirectory.value /
"app/assets",
LessKeys.compress in Assets := true,
includeFilter in (Assets, LessKeys.less) := "*.less",
excludeFilter in (Assets, LessKeys.less) := "_*.less",
pipelineStages := Seq(rjs, gzip)

After your suggestion of running start (I was using run) it seems to
be doing something, at least it does in a sub project i have but when
it seems to go for the main project is stays a lot of time there its
there for like 5 minutes when creating the jar.
Any ideas?

Best Regards,
Rodrigo Fernandes

Megazord

unread,
Jun 21, 2014, 4:34:16 PM6/21/14
to play-fr...@googlegroups.com
Rodrigo,

You have to help me to help you. :-)

What happen after the five minutes? Does it works? Any error message? Are you able to access the application using your browser? Moreover, why are you adding "app/assets" to unmanagedResourceDirectories?

Best,

Rodrigo Fernandes

unread,
Jun 21, 2014, 4:47:19 PM6/21/14
to play-fr...@googlegroups.com
Megazord,

It is still creating the jars I have no output from it since almost 15 minutes.
In relation to the unmanagerResources, i added because saw it on play
migration guide and i think before the less was not being minified
well.
Best Regards,
Rodrigo Fernandes

Christopher Hunt

unread,
Jun 21, 2014, 5:54:59 PM6/21/14
to play-fr...@googlegroups.com
Could I encourage you to post a sample app and describe the steps required to reproduce the problem? It may be best to abandon this thread and raise an issue as such on sbt-web.

Rodrigo Fernandes

unread,
Jun 21, 2014, 5:59:48 PM6/21/14
to play-fr...@googlegroups.com
Christopher and Megazord,

After some tests I removed the assets line on the config and it seems
still fine with the less.
But as soon as I place rjs in the pipeline the app does not end the
creation of the jars.

@Christopher, its kind of hard to reproduce the bug because the
current app is kind of complex. Still I will give it a try.

Besides this, do you have any suggestions to debug this process to see
what is holding the app do finish `activator start`?
Best Regards,
Rodrigo Fernandes

Christopher Hunt

unread,
Jun 21, 2014, 6:02:40 PM6/21/14
to play-fr...@googlegroups.com
I'd say that sbt-rjs is held up with many files to process. Ensure that the engine type is Node, at least for dev.

See the sbt-js-engine README for info in how.

Rodrigo Fernandes

unread,
Jun 21, 2014, 6:10:28 PM6/21/14
to play-fr...@googlegroups.com
Christopher,

I just took a `activator last`:
http://pastebin.com/ztqRj9LY

It seems to be in loop any ideas?
Best Regards,
Rodrigo Fernandes


On Sat, Jun 21, 2014 at 11:02 PM, Christopher Hunt

Rodrigo Fernandes

unread,
Jun 21, 2014, 6:21:18 PM6/21/14
to play-fr...@googlegroups.com
Christopher,

I just tried with that Node engine and seems to be happening exactly the same.
Best Regards,
Rodrigo Fernandes


On Sat, Jun 21, 2014 at 11:02 PM, Christopher Hunt

Rodrigo Fernandes

unread,
Jun 21, 2014, 6:46:39 PM6/21/14
to play-fr...@googlegroups.com
Christopher,

After some time it ended and i have some new input.

  • He says it is uglifying the files and in fact the files inside the build folder are uglyfied, still the files are not in the same path as they were before, I cannot even find them when the app is running, the only files i see are the ones not minified.
  • Other problem is that it is uglifying all the js including libraries we have in the public folder and the css libraries we have how can i exclude them?
Ideas?

Best Regards,
Rodrigo Fernandes

Christopher Hunt

unread,
Jun 21, 2014, 6:54:26 PM6/21/14
to play-fr...@googlegroups.com
sbt-uglify will consolidate all files into one big file. Please raise an issue for sbt-uglify so that we can also min on file by file basis.

To exclude files use an excludeFilter. sbt-less documents an example. Please raise a separate issue for sbt-uglify though as it should perhaps exclude /lib by default.

PRs are also welcomed. :-)

Rodrigo Fernandes

unread,
Jun 21, 2014, 8:08:34 PM6/21/14
to play-fr...@googlegroups.com
Christopher,

I have no permissions to create issues on sbt-uglify.
I took a look at the code and it seems you only need to change the `runUpdate` to map the list `inputFiles` and so you go one by one instead of them all, and then replace the `outputFilewith the same location of the file in relation to the assets folder to maintain the structure inside the build dir.
Since I do not have much experience with that code I did not know how to get only the relative path of the file from the assets root.

Do you have any idea?
What about testing that code how can I import it in my project?




Best Regards,
Rodrigo Fernandes

Christopher Hunt

unread,
Jun 21, 2014, 9:15:59 PM6/21/14
to play-fr...@googlegroups.com
Extending sbt-uglify to provide a source file task should be relatively straightforward. Sbt-web's README documents how to write such a task. 

I've now enabled issues at sbt-uglify (sorry about that) so if you could raise these topics there then that'd be great.

Thanks!

Reply all
Reply to author
Forward
0 new messages