Discussions

News: Jawr: javascript bundling and compression for java applications

  1. Jawr is a tool which helps java web developers in creating and mantaining javascript code using a modular approach, as opposed to mantaining huge and unwieldy .js files. It is also a javascript and CSS compressor that will improve page loading times, by reducing the size of the files to download to be up to seven times smaller. The current trend for richer web applications has led to an increased use of javascript and AJAX. This means that the amount and complexity of javascript code in an average application has grown considerably. It is a good practice to distribute complex code in modules and splitting those in separate files. However, developers must take in account the fact that clients will download javascript using HTTP requests. Browsers will typically make only two requests concurrently to the same host, so the more files to download, the longer it takes to load a page. Therefore, a heavily modularized javascript codebase may have a unacceptable impact in page download times. There is a great article by Flickr developer Cal Henderson, explaining how the number of requests affects page download times here: Serving JavaScript Fast. So how is this problem normally solved? The common approaches often affect the ease of development:
    • The simplest way of dealing with this is to put all modules in one or two huge .js files. These files are obviously hard to mantain: modules are hard to find, concurrent changes by more than one developer have to be merged, and it becomes difficult to track changes to specific modules in version control.
    • On the other hand, a script may be developed to join all the modules at build time. This has the disadvantage of forcing a full rebuild-redeploy cycle to test the slightest change in javascript code at development time. Besides, the build script must be created and mantained. Medium size or smaller projects will normally go for the first method.
    Jawr allows to create virtual .js and .css files, called bundles. With a simple .properties file, individual files or whole directories are added to these bundles. It works the following way:
    • When deployed in production servers, Jawr compresses and joins all the files that belong to each bundle. The bundles are created in uncompressed and gzipped form upon server startup, so there is no processing overhead to javascript requests.
    • A tag library is used to generate links on the pages, which will convert a reference to a specific module into a link to the bundle it belongs to.
    • A servlet will attend requests for .js and .css files, and will send gzipped bundles to gzip-enabled browsers.
    Jawr also has a development mode in which bundles are not used on the client side. Instead, each individual module is loaded separately and with no compression. This allows developers to work on an exploded WAR directory, making changes to CSS and javascript and testing them by refreshing the page which loads them. Changing from production to development mode only takes changing a flag at the configuration .properties file. Other features include caching enforcement techniques to improve load times once a user has downloaded a bundle, the ability to declare global bundles which are automatically included before any other script, an easy mechanism to specify the order in which files are added to bundles, etc. Jawr is also thoroughly documented. Downloads and documentation can be found at https://jawr.dev.java.net/.

    Threaded Messages (19)

  2. Nice, another alternative is here http://js-optimizer.sourceforge.net/
  3. docs[ Go to top ]

    If I had to choose I'd go with jawr based on the quality of its documentation alone. Seems pretty comprehensive and well written. Nice job. Will have to have a play later on.
  4. I didn't know about that one. It does seem quite similar. There is also another alternative: pack:tag, although it doesn't focus as much in bundling (while it does allow to) as it does in offering different compression modes.
  5. If you want resource bundeling[ Go to top ]

    Javascript compression is not there yet but weblets.dev.java.net basically does the same. You basically can achieve neutral namespace packaging simply via an internal neutral notation which is independent of the physical location. The notation is different however, instead of bundles you have weblets which basically are a name, location, loading mechanism indirection and to load resources you basically use a neutral weblet:url('webletname','logicallocation') notation While it does not have javascript compression, it is more generic and has framework adapters into various webframework base technologies.
  6. Re: If you want resource bundeling[ Go to top ]

    After a quick look at webloets, it seems to me it is more oriented towards serving javascript from jar files (a feature not present in Jawr). Does it join .js files? Also, it does not provide with a JSP 1.x tag library. Finally, it seems like it does not have a development mode like that of Jawr, where files in a bundle are linked and served separately. The main target of Jawr is to allow developers to split and organize their code in a more efficient way, without worrying about the way files will be served. The bundling mechanism is not meant to distribute the code in jar files, but rather as a way to allow to organize the code in a particular project. Compression is an obvious addition to the execution chain, but it is more of an afterthought. So I think Jawr and weblets have different goals. As to being more generic, you can use Jawr along with any java framework as long as the view technology is JSP (i.e. you could use with JSF unles you are using Facelets).
  7. Re: If you want resource bundeling[ Go to top ]

    After a quick look at webloets, it seems to me it is more oriented towards serving javascript from jar files (a feature not present in Jawr). Does it join .js files?
    No, this probably never will be the goal of weblets at least it is not for now due to the fact that it tries to concentrate itself on a more generic approach of resource loading itself.

    Also, it does not provide with a JSP 1.x tag library.
    Yes and no, we discussed a tag lib approach, but omitted it in favor of a more generic bean approach and el functions for jsp 2.x. The code still is in there but wont be activated for 1.0
    Finally, it seems like it does not have a development mode like that of Jawr, where files in a bundle are linked and served separately.
    The main target of Jawr is to allow developers to split and organize their code in a more efficient way, without worrying about the way files will be served. The bundling mechanism is not meant to distribute the code in jar files, but rather as a way to allow to organize the code in a particular project. Compression is an obvious addition to the execution chain, but it is more of an afterthought.
    So I think Jawr and weblets have different goals.

    As to being more generic, you can use Jawr along with any java framework as long as the view technology is JSP (i.e. you could use with JSF unles you are using Facelets).
    Point taken, I should have read the docs more thoroughly before posting, btw. you could easily add facelet support via el functions or jsf dummy maps, or a full blown tag, just a hint.
  8. Re: If you want resource bundeling[ Go to top ]

    Thanks for the tip on facelets support, I might look into it for later versions.
  9. This begs me to ask about similarities to GWT javascript obfuscation capabilities. GWT also offers image bundling to reduce i/o. I assume this works best with an existing codebase.
  10. dojo shrinksafe is the same thing[ Go to top ]

    dojo shrinksafe lets you do the same.
  11. @Andrew: of course, if you are using GWT you don't need Jawr. But if you are not, do you know if these obfuscation and bundling capabilities can be used? I've never looked into GWT (though I mean to soon) and I am curious. @Anthony: Dojo shrinksafe is a javascript compressor. Jawr does use a javascript compressor under the hood (JsMin to be precise). But if you carefully read the article, you will understand that the idea behind Jawr goes beyond that. For example, it allows you to swicth bundling and compression on and off without having to change anything more than a flag, it also enables to serve gzipped content, and many more things that are beyond what a compressor offers. If you visit the project's page, you will see that the 'tagline' for Jawr is "more than a javascript/CSS compressor".
  12. There are several filters in JSOS: http://www.servletsuite.com/servlets/trimflt.htm http://www.servletsuite.com/servlets/jstrimflt.htm http://www.servletsuite.com/servlets/csstrimflt.htm
  13. As I said, Jawr does more than just compress, it is a mechanism to join many .js or .css files into a minified and compressed resource. Also, Jawr is licensed under the Apache 2.0 license, meaning it is free to use for commercial purposes.
  14. Awesome[ Go to top ]

    Hi, This is a very good technology ,where in the current world ,both Quality and quantity matters .This thing has proved that ,moreover it saves a lot of time and hence makes easy for the developer ... Thanks & regards. sarath Meruga
  15. Great idea, needs more work IMHO[ Go to top ]

    This is a great idea. I also wanted to write this too. But this is putting more rules on you to do stuff. There are already so many rules and frameworks to learn. From what I understand, it expects you to organize all your js files into modules and encourages to use only two modules in page (assuming the browser limit as 2). But real life scenario is far from this. In some scenarios, you might want 10 different files out of 10 different modules, but at the same time not the whole modules. Instead of enforcing modules and all that, Better idea would be to let the developer supply list of all js files needed on a jsp (lets say abc.jsp) to the taglib and concatenate&compress it at runtime. So there will be a hit in terms of speed for the first request for abc.jsp (not for every user), which is mostly acceptable. At this point maintain a mapping between page and list of js files. For subsequent requests, just use this mapping and serve. Concept is very similar to JSPs compilation. This way, you are not enforcing anything new on developer and serves the purpose when there is adhoc imports of js files.
  16. What I mean by this is, output the name of the newly concatenated, compressed js file (or may be two files) into JSP. So that way, everything is taken care of the first time and this framework is out of picture for subsequent requests. And may be name the generated js file with compile time timestamp, so it can be cached and still be different on next compile. In dev mode, it does not have to do anything except write out HTML script tags in to JSP. This is the most un-obtrusive way this situation can be handled.
    At this point maintain a mapping between page and list of js files. For subsequent requests, just use this mapping and serve.
  17. Hi Krishna, thanks for your comments. I'll try to address what you said:
    But this is putting more rules on you to do stuff. There are already so many rules and frameworks to learn.
    This is so true, if I have a gripe about java development is how much stuff people needs to learn just to get on the tracks of it. However, I think once Jawr has been set up it needs very little maintenance in terms of configuration. Also, in most cases the config file would be around 10-20 lines, so no huge descriptors here. As for the tag libraries, I don't think they should take more than two minutes to learn. So a lead developer may take care of writing the descriptor, and everyone else only needs a couple minutes to learn how to use the tags and the development mode.
    ...encourages to use only two modules in page (assuming the browser limit as 2). But real life scenario is far from this. In some scenarios, you might want 10 different files out of 10 different modules, but at the same time not the whole modules.
    You can use as many modules in a page as you need to. Jawr helps you load as little files as possible per page by creating bundles. The modules live in these bundles. Of course you will not need them all at once, but think that, once a user has loaded a bundle once, it will be cached. Jawr serves files using many techniques to force the browser to cache the bundles. For example: if page A uses modules Foo and Fuz, and page B uses module Bar and Fuz, what happens is: * User visits page A, downloads a bundle with Foo and Bar. Bar is not used. * User visits page B, Bar and Fuz are retrieved from cache, the page loads very quickly since the bundle is not downloaded again. So even if a bundle contains modules not needed by a page, it is better to keep things together. If you made a different bundle for every page, this is what would happen: * User visits page A, downloads a bundle with Foo and Fuz. * User visits page B, downloads a bundle with Bar and Fuz. You just lost any chance of retrieving Fuz from the cache. Instead, the user downloaded it twice. If you scale this to a whole application, you are not really going to have good performance.
    Better idea would be to let the developer supply list of all js files needed on a jsp (lets say abc.jsp) to the taglib and concatenate&compress it at runtime.
    Actually, you can do that exactly using the pack:tag. You might want to check it out. I coded Jawr because I wanted to implement an external, dynamic mapping of reusable bundles. With the pack tag, if I want to reuse a bundle I must repeat its definition on every page that uses it. And if I add a new module to the bundle, I must go over every page and change it. With Jawr, I only need to place a new file under a mapped dir and it is automatically added to a bundle. Otherwise, the pack:tag is a nice, stable alternative and supports many minification tools.
    What I mean by this is, output the name of the newly concatenated, compressed js file (or may be two files) into JSP. So that way, everything is taken care of the first time and this framework is out of picture for subsequent requests.
    There is aproblem there: as far as I know, you can't create new files inside a WAR archive and let the web container serve them. So you whatever you create, it must be created under a temporary directory, and you must use a servlet to read and serve whatever you created (or otherwise cache it and serve from memory, which Jawr supports).
  18. I appreicate the detailed response and now I understand this a little better. Thanks.
    Hi Krishna, thanks for your comments. I'll try to address what you said:

    But this is putting more rules on you to do stuff. There are already so many rules and frameworks to learn.

    This is so true, if I have a gripe about java development is how much stuff people needs to learn just to get on the tracks of it. However, I think once Jawr has been set up it needs very little maintenance in terms of configuration. Also, in most cases the config file would be around 10-20 lines, so no huge descriptors here. As for the tag libraries, I don't think they should take more than two minutes to learn. So a lead developer may take care of writing the descriptor, and everyone else only needs a couple minutes to learn how to use the tags and the development mode.

    ...encourages to use only two modules in page (assuming the browser limit as 2). But real life scenario is far from this. In some scenarios, you might want 10 different files out of 10 different modules, but at the same time not the whole modules.

    You can use as many modules in a page as you need to. Jawr helps you load as little files as possible per page by creating bundles. The modules live in these bundles. Of course you will not need them all at once, but think that, once a user has loaded a bundle once, it will be cached. Jawr serves files using many techniques to force the browser to cache the bundles.

    For example: if page A uses modules Foo and Fuz, and page B uses module Bar and Fuz, what happens is:

    * User visits page A, downloads a bundle with Foo and Bar. Bar is not used.

    * User visits page B, Bar and Fuz are retrieved from cache, the page loads very quickly since the bundle is not downloaded again.

    So even if a bundle contains modules not needed by a page, it is better to keep things together. If you made a different bundle for every page, this is what would happen:

    * User visits page A, downloads a bundle with Foo and Fuz.

    * User visits page B, downloads a bundle with Bar and Fuz.

    You just lost any chance of retrieving Fuz from the cache. Instead, the user downloaded it twice. If you scale this to a whole application, you are not really going to have good performance.

    Better idea would be to let the developer supply list of all js files needed on a jsp (lets say abc.jsp) to the taglib and concatenate&compress it at runtime.

    Actually, you can do that exactly using the pack:tag. You might want to check it out. I coded Jawr because I wanted to implement an external, dynamic mapping of reusable bundles. With the pack tag, if I want to reuse a bundle I must repeat its definition on every page that uses it. And if I add a new module to the bundle, I must go over every page and change it. With Jawr, I only need to place a new file under a mapped dir and it is automatically added to a bundle. Otherwise, the pack:tag is a nice, stable alternative and supports many minification tools.

    What I mean by this is, output the name of the newly concatenated, compressed js file (or may be two files) into JSP. So that way, everything is taken care of the first time and this framework is out of picture for subsequent requests.

    There is aproblem there: as far as I know, you can't create new files inside a WAR archive and let the web container serve them. So you whatever you create, it must be created under a temporary directory, and you must use a servlet to read and serve whatever you created (or otherwise cache it and serve from memory, which Jawr supports).
  19. You can put common scripts in the jsp include file. And use Granule http://code.google.com/p/granule/

  20. Re: Great idea, needs more work IMHO[ Go to top ]

    We we have been tackling these CSS & JS performance issues in the Click Framework as well. These issues are really well articulated in the Yahoo Performance Best Practices: http://developer.yahoo.com/performance/rules.html We didn't go down the build approach (because of the work it would added to developers) but tried to address these issues through: * versioning static resources (css, js, images), and applying long expiry headers * applying GZIP compression to these imports We also separated out CSS and JS imports into separate "tags" at the top and bottom of pages to support progressive rendering. This code ensures imports aren't duplicated and JS import dependency order is preserved. You can see this online at: http://www.avoka.com:8080/click-examples/home.htm For more details see: http://click.sourceforge.net/docs/extras-api/net/sf/click/extras/filter/PerformanceFilter.html regards Malcolm Edgar http://click.sourceforge.net