Showing posts with label Optimization. Show all posts
Showing posts with label Optimization. Show all posts

Sunday, June 14, 2015

Create source maps at project build time for JavaScript debugging

If you're doing front end web development, your web resources such as JavaScript and CSS files might be minificated, transpiled or compiled from a completely different language. If you now want to debug the generated code in the browser, you can not do that because the output code is obfuscated from the code you wrote. The solution is to use source maps. A good introduction to the source map can be found in the articles "Introduction to JavaScript Source Maps", "Enhance Your JavaScript Debugging with Cross-Browser Source Maps" and "An Introduction to Source Maps".

I will try to summarize the quintessence about the source maps and concentrate on JavaScript only. Generating CSS by LESS / SASS is interesting too, but it is not yet supported by my Maven plugin I will present in this blog post. How to use a source map? In order to use a source map, your browser development tools need to be able to find it. If your generated code is JavaScript, one way to let the development tools know where to look is to add a comment to the end of the generated code which defines the sourceMappingURL - the location of the source map. For example: //# sourceMappingURL=mylib.js.map or //# sourceMappingURL=/mypath/mylib.js.map or //# sourceMappingURL=http://sourcemaps/mylib.js.map. If you now open a development tool and the source map support is enabled, the browser will stream down the source map which points to the original file and show the original file instead of generated one (minificated, compiled, transpiled, etc.). Now, you can set a breakpoint in the original file and debug it as it would be delivered with you web application! Such debugging is possible due to the fact that a source map provides a way of mapping code within a generated file back to it's original position in a source file. I found a nice bild here to visualize the entire process.


Source maps are supported in all major browser that are shipped with built-in support for source maps. If you follow my links to the articles I mentioned above, you can see some examples for Internet Expoler 11, Firefox and Google Chrome. Chrome's Dev Tools enables the source maps support by default. Simple check if the checkbox "Enable JavaScript source maps" is enabled.


If you a fan of Firefox, you should use the Firefox' Web Console (Shift + Ctrl + K) and check if the same option is enabled in settings too. Please note that Firebug doesn't support debugging by source maps. You have to use the native Firefox' Web Console as I said. Internet Explorer 11 also rocks with source maps. It has even more features - you can add source map files from your local disk. Simple right-click on a generated (e.g. compressed) file and select "Choose source map". The article "Enhance Your JavaScript Debugging with Cross-Browser Source Maps" which I mentioned above, has a lot of picture for IE and debugging TypeScript files.

Source maps can be created during your build. If you work with Node.js and npm, the best tool is UglifyJS - a popular command line utility that allows you to combine and compress JavaScript files. If you work with Maven, you can use my Maven plugin for resource optimization I wrote a some years ago and just updated for supporting source maps. It uses the superb Google Closure Compiler which offers a support for source map creation and many other cool features. Please refer the documentation of the Maven plugin to see how to set the various source map configuration options. The simplest configuration which we also use in the current PrimeFaces Extensions release looks like as follows:
<plugin>
    <groupId>org.primefaces.extensions</groupId>
    <artifactId>resources-optimizer-maven-plugin</artifactId>
    <version>2.0.0</version>
    <configuration>
        <sourceMap>
            <create>true</create>
            <outputDir>${project.basedir}/src/sourcemap/${project.version}</outputDir>
            <sourceMapRoot>
              https://raw.githubusercontent.com/primefaces-extensions/core/master/src/sourcemap/${project.version}/
            </sourceMapRoot>
        </sourceMap>
    </configuration>
    <executions>
        <execution>
            <id>optimize</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>optimize</goal>
            </goals>
        </execution>
    </executions>
</plugin>
By this way, only compressed JavaScript files will be packaged within released JAR file. Uncompressed files are not within the JAR. The JAR is smaller and free from redundant stuff. For the PrimeFaces Extensions, the source map and uncompressed files are checked in below the project root. For example, the folder with source maps and original files for the current release 3.2.0 is located here: https://github.com/primefaces-extensions/core/tree/master/src/sourcemap/3.2.0 That means, a compressed file, say timeline.js, has the following line at the end:

//# sourceMappingURL=https://raw.githubusercontent.com/primefaces-extensions/core/master/src/sourcemap/3.2.0/timeline.js.map

The source map timeline.js.map has the content (I truncated some long lines):
{
  "version":3,
  "file":"timeline.js",
  "lineCount":238,
  "mappings":"A;;;;;;;;;;;;;;;;;;;;AA4DqB,WAArB,GAAI,MAAOA,MAAX,GACIA,KADJ,CACY,EADZ,CAUsB,YAAtB,GAAI,...
  "sources":["timeline.source.js"],
  "names":["links","google","undefined","Array","prototype","indexOf","Array.prototype.indexOf",...]
}
It would be probably better to bring these files to a CDN, like cdnjs, but CDNs are not really intended for source maps. Another option would be a PrimeFaces repository. We will see how to handle that in the future. The next picture demonstrates how the debugging for the compressed JS file timeline.js looks in my Firefox.


Due to the Firefox built-in source map support we see the uncompressed JS file timeline.source.js. I set a breakpoint on the line with the if-statement if (index < 0). After that I clicked on an event in the Timeline component. The breakpoint was jumped up. Now, I can debug step by step and see my local and global variables on the right side. As you probably see, the variable index is shown as a (I marked it red as var index). This is a shortcoming of the current source map specification. You can read this discussion for more details.

Again, keep in mind - the source maps and original files will be only loaded when you open up the browser dev. tools and enable this support explicitly. If the dev. tools has identified that a source map is available, it will be fetched along with referenced source file(s). If a source map file is not available, you will see a 404 "not found message" in the dev. tool (not bad at all in my opinion).

That's all. My next posts will be about AngularJS and less about JSF. Stay tuned.

Thursday, November 20, 2014

Don't repeat expressions in facelets

Have you ever seen repeated EL expressions in JSF like this one?
<h:inputText value="#{oneBean.name}" rendered="#{anotherBean.showPerson}"/>
<h:inputText value="#{oneBean.birthday}" rendered="#{anotherBean.showPerson}"/>
<h:selectOneMenu value="#{oneBean.children}" style="#{anotherBean.showPerson ? 'display:block' : 'display:none'}"/>
usw. Another example:
<ui:include src="/include/somesnippet.xhtml">
    <ui:param name="age" value="#{someBean.isMan(person) ? 63 : 60}"/>
    <ui:param name="money" value="#{someBean.isMan(person) and someBean.getCountry(person) eq 'de' ? 1000 : 900}"/>
    <ui:param name="big" value="#{someBean.getCountry(person) eq 'zh' or someBean.getCountry(person) eq 'ru' ? true : false}"/>
</ui:include>
Expressions #{anotherBean.showPerson}, #{someBean.isMan(person)}, #{someBean.getCountry(person)} are repeated multiple times. How to optimize them? Well, you can use JSTL's c:set like this code snippet
<c:set var="showPerson" value="#{anotherBean.showPerson}"/>

<h:inputText value="#{oneBean.name}" rendered="#{showPerson}"/>
<h:inputText value="#{oneBean.birthday}" rendered="#{showPerson}"/>
<h:selectOneMenu value="#{oneBean.children}" style="#{showPerson ? 'display:block' : 'display:none'}"/>

<c:set var="man" value="#{someBean.isMan(person)}"/>
<c:set var="country" value="#{someBean.getCountry(person)}"/>

<ui:include src="/include/somesnippet.xhtml">
    <ui:param name="age" value="#{man ? 63 : 60}"/>
    <ui:param name="money" value="#{man and country eq 'de' ? 1000 : 900}"/>
    <ui:param name="big" value="#{country eq 'zh' or country eq 'ru' ? true : false}"/>
</ui:include>
If you are scared about JSTL pitfalls (because you have heard that JSTL is not always JSF friendly :-)), there is an alternative and simple approach - ui:param. TagHandler ui:param uses JSF's VariableMapper to save EL expressions in a map. This map maps EL variables on a page and the EL expressions they are associated with. And here you go:
<ui:param name="showPerson" value="#{anotherBean.showPerson}"/>

<h:inputText value="#{oneBean.name}" rendered="#{showPerson}"/>
<h:inputText value="#{oneBean.birthday}" rendered="#{showPerson}"/>
<h:selectOneMenu value="#{oneBean.children}" style="#{showPerson ? 'display:block' : 'display:none'}"/>

<ui:param name="man" value="#{someBean.isMan(person)}"/>
<ui:param name="country" value="#{someBean.getCountry(person)}"/>

<ui:include src="/include/somesnippet.xhtml">
    <ui:param name="age" value="#{man ? 63 : 60}"/>
    <ui:param name="money" value="#{man and country eq 'de' ? 1000 : 900}"/>
    <ui:param name="big" value="#{country eq 'zh' or country eq 'ru' ? true : false}"/>
</ui:include>
The code is more readable, especially if you have very complex and long expressions. Note: we're speaking here about readable code and not about performance optimization because JSF TagHandlers don't evaluate EL expressions.

Tuesday, May 7, 2013

JSF: choice between legacy components and fashionable performance killers

This blog post was originated due to performance issues in one big web application. Everybody optimizes Java code, but it seems nobody try to optimize the JavaScript code. Strange, because on the client-side there is much room for improvements. I would state, even more than on the server-side. We will analyse the perfomance of editable JSF standard components, sometimes called "legacy", and modern PrimeFaces components with rich JavaScript widgets. This is a neutral analyse, without to blame any library or any person. Only facts.

Well. What do we want to test? The goal is to measure the client-side perfomance (without backend logic) of JS script block executions for PrimeFaces p:inputText / p:selectOneMenu. We want to test an editable p:dataTable with inputs / selects components in table cells. The table has 25 rows and 16 columns, that means 25 * 16 = 400 cells. Every cell contains either an input or a select component. There are 6 test cases. Standard h:inputText and h:selectOneMenu don't have JS script blocks, so it is interesting to see what for impact JS widgets have.


The entire test project is available on GitHub. Simple clone or download it and run with built-in Maven Jetty plugin. The page load speed is measured with the new Navigation Timing JavaScript API for accurately measuring performance on the web. The API provides a simple way to get accurate and detailed timing statistics. It's more precise than using JS Date object. The Navigation Timing JavaScript API is available in Internet Explorer 9 and higher, last versions of Google Chrome and Firefox. The code to measure the time after the current response has been arrived until the window onload event is fired is shown on the GitHub.

JavaScript is single-threaded, so let's see how sequential script block executions can slow down displaying a web page. If we only test h:inputText and p:inputText, the difference is marginal. The page load time is almost the same. Running on Windows 7 and Firefox 20.0.1 I could only see that the table with p:inputText needs ca. 200-300 ms more than the table with h:inputText. This is a good result which means the JS script execution for one p:inputText takes less than 1 ms. Really good. Congrats to PrimeFaces. A mix test with inputs and selects shown that the page with PrimeFaces components takes approximately 1.5 sek. more than the page with standard components. Adding more PrimeFaces select components slows the page rendering time down. Extreme case is to have only p:selectOneMenu components. This is a perfomance killer and the reason why our web application was too slow. Internet Explorer shows the well-known error message "A script on this page is causing Internet Explorer to run slowly". Take a look at page load time self.

Running on Windows 7 and Firefox 20.0.1

h:selectOneMenu

 

p:selectOneMenu


If we assume that component renderers take approximately the same time to render HTML output, we can calculate the time for JS script block execution of a single p:selectOneMenu. This time is 11,3 ms. That's too much. The reason may be many inefficient jQuery selectors in widget's constructor. I don't know and it doesn't matter here. On my notebook with Ubuntu, I got a huge time difference ca. 10 sek. The browser with 400 p:selectOneMenu tags almost "freezes".

Running on Kubuntu 12.04 and Firefox 20.0

h:selectOneMenu


p:selectOneMenu


Conclusion

Some people say "JSF is slow, JSF is not a right technology". Wrong. JSF is fast enough. It depends on how to use this framework. Editing of everything at once is nice, but obviously it is not recommended to use a large editable DataTable with rich JSF components. What would be an alternative for editable DataTable? There are many ways, depending on individual preferences. I will try to propose some ones.
  1. Use standard JSF select components in large editable tables. But what is with theming? No problem. All modern browser, also IE8 and higher allow to style native HTML select elements. You can adjust colors for borders, background and let selects look more or less stylish according to applied theme. Presupposed is of course, you don't need advanced features such as custom content within select components (filter functionality or whatever).
  2. Cell editing feature in PrimeFaces renders native select elements and it is fast.
  3. Row editing feature in PrimeFaces renders native select elements and it seems to be also fast.
  4. Master-Detail approach in one view. You select a row and see details to edit. Details can be shown outside of the table - on the right side or at the top, depending on table's width / height.
  5. Master-Detail approach with separate views. You select a row and switch the views. Instead of table, you see details like in the MasterDetail component of PrimeFaces Extensions. From details you can go on to another levels to create / edit more details and then, at the end, jump to the overview table again.
I hope, you enjoyed this post :-). Comments and suggestions are welcome.

Sunday, April 15, 2012

High Performance Webapps. Use Data URIs. Practice.

This post continues the started discussion about data URIs. The first question is if it's worth to put data URIs in style sheets? Yes, it's worth. First, I would like to point you to this great article "Data URIs for CSS Images: More Tests, More Questions" where you can try to test all three scenarios for your location. Latency is different depending on your location. But you can see a tendency that a web page containing data URIs is loaded faster. We can see one of the main tricks to achieve better performance with data URIs:

Split your CSS in two files - one with main data and one with data URIs only and place the second one in the footer. "In the footer" means close to the HTML body tag. Page rendering feels faster then because of the progressive rendering. In the second article you can see that this technique really accelerates page rendering. Style sheet in footer leads to a nice effect that large images download in parallel with the data URI style sheet. Why? Well, browser thinks stuff placed in footer can not have any impact on page structure above included files and doesn't block resource loading. I also read that in this case all browsers (except old IE versions) render a page immediately without waiting until CSS with data URIs has been loaded. The same is valid for JavaScript files, as far as I know. Is it valid at all to put CSS files in page footer? Well, it's not recommended in the HTML specification. But it's valid in practice and it's not bad at all in special cases. There is an interesting discussion on Stackoverflow "How bad is it to put a CSS include in the middle of the body?"

The second tip is to use data URIs for small images, up to 1-2 KB. It's not worth to use data URIs for large images. A large image has a very long data URI string (base64 encoded string) which can increase the size of CSS file. Files with a big size can block loading of other files. Remember, browsers have connection limitations. They can normally open 2-8 conection to the same domain. That means only 2-8 files can be loaded parallel at the same time. After reading some comments in internet I got an acknowledge about my assumption with 1-2 KB images.

We can soften this behavior by using of GZIP filter. A GZIP filter reduces size of resources. I have read that sometimes the size of an image encoded as data URI is even smaller than the size of original image. A GZIP filter is appled to web resources like CSS, JavaScript and (X)HTML files. But it's not recommended to apply it to images and PDF files e.g. So, not encoded images aren't going through the filer, but CSS files are going through. In 99%, if you gzip your CSS file, the resulting size is about the same as the regular image URL reference! And that was the third tip - use a GZIP filter.

I would like to show now my test results. My test environment: Firefox 11 on Kubuntu Oneiric. I prepared the showcase of PrimeFaces Extensions with 31 images which I added to the start page. These images display small themes icons in PNG format. Every image has the same size 30 x 27 px. Sizes in kilobytes lie in range 1.0 - 4.6 KB. CSS file without data URIs was 4.8 KB and with data URIs 91,6 KB. CSS files were included quite normally in HTML head section, by the way. I deployed showcases with and without data URIs on my VPS with Jetty 8 server. First without a GZIP filer. I cleared browser cache and opened Firebug for each showcase. Here results:

Without data URIs:

65 requests. Page loading time 3.84s (onload: 4.14s).

That means, document ready event occured after 3.84 sek. and window onload after 4.14 sek. Subsequent calls for the same page (resources were fetched from browser cache) took 577 ms, 571 ms, 523 ms, ...

With data URIs:

34 requests. Page loading time 3.15s (onload: 3.33s).

That means, fewer requests (remember 31 embedded images), document ready event occured after 3.15 sek. and window onload after 3.33 sek. Subsequent calls for the same page (resources were fetched from browser cache) took 513 ms, 529 ms, 499 ms, ...

There isn't much difference for subsequent calls (page refreshes), but there is a significant difference for the first time visiting. Especially onload event occurs faster with data URIs. No wonder. Images being loading after document is ready. Because they can not be loaded parallel (number of opened connection is limited), they get blocked. I took some pictures from Google Chrome Web Inspector. Below you can see timing for an image (vader.png) for the first (regular) case without data URI.


And the second case for the same image encoded as data URI.


You see in the second picture there isn't any blocking at all. Tests with a GZIP Filter didn't have much impact in my case (don't know why, maybe I haven't too much resources). Average times after a couple of tests with empty cache:

Without data URIs:

65 requests. Page loading time 3.18s (onload: 3.81s).

With data URIs:

34 requests. Page loading time 3.03s (onload: 3.19s).

Any questions?

Saturday, April 14, 2012

High Performance Webapps. Use Data URIs. Theory.

I continue to write tips for perfomance optimization of websites. The last post was about jQuery objects. This post is about data URIs. Data URIs are an interesting concept on the Web. Read "Data URIs explained" please if you don't know what it does mean. Data URIs are a technique for embedding resources as base 64 encoded data, avoiding the need for extra HTTP requests. It gives you the ability to embed files, especially images, inside of other files, especially CSS. Not only images are supported by data URIs, but embedded inline images are the most interesting part of this technique. This technique allows separate images to be fetched in a single HTTP request rather than multiple HTTP requests, what can be more efficient. Decreasing the number of requests results in better page performance. "Minimize HTTP requests" is actually the first rule of the "Yahoo! Exceptional Performance Best Practices", and it specifically mentions data URIs.

"Combining inline images into your (cached) stylesheets is a way to reduce HTTP requests and avoid increasing the size of your pages... 40-60% of daily visitors to your site come in with an empty cache. Making your page fast for these first time visitors is key to a better user experience."

Data URI format is specified as

data:[<mime type>][;charset=<charset>][;base64],<encoded data>

We are only interesting for images, so that mime types can be e.g. image/gif, image/jpeg or image/png. Charset should be omitted for images. The encoding is indicated by ;base64. One example of a valid data URI:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
        AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
        9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot">
HTML fragments with inline images like the above example are not really interesting because they are not cached. Data URIs in CSS files (style sheets) are cached along with CSS files and that brings benefits. Some advantages describing in Wikipedia:
  1. HTTP request and header traffic is not required for embedded data, so data URIs consume less bandwidth whenever the overhead of encoding the inline content as a data URI is smaller than the HTTP overhead. For example, the required base64 encoding for an image 600 bytes long would be 800 bytes, so if an HTTP request required more than 200 bytes of overhead, the data URI would be more efficient.
  2. For transferring many small files (less than a few kilobytes each), this can be faster. TCP transfers tend to start slowly. If each file requires a new TCP connection, the transfer speed is limited by the round-trip time rather than the available bandwidth. Using HTTP keep-alive improves the situation, but may not entirely alleviate the bottleneck.
  3. When browsing a secure HTTPS web site, web browsers commonly require that all elements of a web page be downloaded over secure connections, or the user will be notified of reduced security due to a mixture of secure and insecure elements. On badly configured servers, HTTPS requests have significant overhead over common HTTP requests, so embedding data in data URIs may improve speed in this case.
  4. Web browsers are usually configured to make only a certain number (often two) of concurrent HTTP connections to a domain, so inline data frees up a download connection for other content.
Furthermore, data URIs are better than sprites. Images organized as CSS sprites (many small images combined to one big) are difficult to be maintained. Maintenance costs are high. Imagine, you want to change some small images in the sprite, their position, size, color or whatever. Well, there are tools allowing to generate sprites, but later changes are not easy. Especially changes in size cause a shift of all positions and a lot of CSS changes. And don't forget - a sprite still requires one HTTP request :-).

What browsers support data URIs? Data URIs are supported for all modern browsers: Gecko-based (Firefox, SeaMonkey, Camino, etc.), WebKit-based (Safari, Google Chrome), Opera, Konqueror, Internet Explorer 8 and higher. For Internet Explorer 8 data URIs must be smaller than 32 KB. Internet Explorer 9 does not have this 32 KB limitation. IE versions 5-7 lack support of data URIs, but there is MHTML – when you need data URIs in IE7 and under.

Are there tools helping with automatic data URI embedding? Yes, there are some tools. The most popular is a command line tool CSSEmbed. Especially if you need to support old IE versions, you can use this command line tool which can deal with MHTML. Maven plugin for web resource optimization, which is a part of PrimeFaces Extensions project, has now a support for data URIs too. The plugin allows to embed data URIs for referenced images in style sheets at build time. This Maven plugin doesn't support MHTML. It's problematic because you need to include CSS files with conditional comments separately - for IE7 and under and all other browsers. How does the conversion to data URIs work?
  1. Plugin reads the content of CSS files. A special java.io.Reader implementation looks for tokens #{resource[...]} in CSS files. This is a syntax for image references in JSF 2. Token should start with #{resource[ and ends with ]}. The content inside contains image path in JSF syntax. Theoretically we can also support other tokens (they are configurable), but we're not interested in such kind of support :-) Examples:
    .ui-icon-logosmall {
        background-image: url("#{resource['images/logosmall.gif']}") !important;
    }
    
    .ui-icon-aristo {
         background-image: url("#{resource['images:themeswitcher/aristo.png']}") !important;
    }
    
  2. In the next step the image resource for each background image is localized. Images directories are specified according to the JSF 2 specification and suit WAR as well as JAR projects. These are ${project.basedir}/src/main/webapp/resources and ${project.basedir}/src/main/resources/META-INF/resources. Every image is tried to be found in those directories.
  3. If the image is not found in the specified directories, then it doesn't get transformed. Otherwise, the image is encoded into base64 string. The encoding is performed only if the data URI string is less than 32KB in order to support IE8 browser. Images larger than that amount are not transformed. Data URIs looks like
    .ui-icon-logosmall {
        background-image: url("data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgA ... ASUVORK5CYII=") !important;
    }
    
    .ui-icon-aristo {
        background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgA ... BJRU5ErkJggg==") !important;
    }
    
Configuration in pom.xml is simple. To enable this feature set useDataUri flag to true. Example:
<plugin>
    <groupId>org.primefaces.extensions</groupId>
    <artifactId>resources-optimizer-maven-plugin</artifactId>
    <configuration>
        <useDataUri>true</useDataUri>
        <resourcesSets>
            <resourcesSet>
                <inputDir>${project.build.directory}/webapp-resources</inputDir>
            </resourcesSet>
        </resourcesSets>
    </configuration>
</plugin>
Enough theory in this post. The next one will describe a practice part. I will expose some measurements, screenshots and give tips how large images should be, where CSS should be placed, what is the size of CSS file with data URIs and whether a GZIP filter can help here. Stay tuned.

Thursday, March 22, 2012

High Performance Webapps. jQuery Objects as Arrays.

After recently participation in a workshop Real Life JS: High Performance Webapps. I have decided to share some tricks to achieve better perfomance for websites. There are 100+ tricks. It's impossible to covers all of them. In this post I would like to show a difference between using of jQuery calls and JavaScript native ones. Especially using of $.each() method for iteration is the topic of this post. I already knew that using of $.each() is slow. This fact is described in 15 Powerful jQuery Tips and Tricks for Developers (chapter 3). What is an alternative to $.each()? How to iterate faster on result set of running a selector? The result of running a selector is an jQuery object. However, the library makes it appear as if you are working with an array by defining index elements and a length. Use a native JavaScript for or while loop on the result. Check this example please. Perfomance benefit is huge in my opinion. I also learned that any method call in JavaScript brings a lot of overhead. I also learned that literal notation like this one
var myArray = [];
var newElement = "test element";
myArray[myArray.length] = newElement;
always works faster than
var myArray = new Array();
var newElement = "test element";
myArray.push(newElement);
Never call new operator if you can use literal notations for arrays and objects in JavaScript. Never call methods like push() if you can do this in another way. Difference in execution time of the code parts above is significant in loops. The main rule here: "Less operations per iteration - less execution time. Doing nothing is the best from performance point of view". An example of bad programming would be
for(var i=0; i < myArray.length; i++) {
    ...
}
because length is not cached and myArray.length is executed for each iteration step.

Today, I've played a little bit with the new great feature in PrimeFaces jQuery Selector API meets JSF. My aim was to compare $.each(), array's push() and $.attr() calls with native JavaScript calls. I prepared a small test page with a simple selector and the code from PrimeFaces core.js. Alternative I rewritten the code in PrimeFaces with native calls to show the difference. First, I ended up with this code. The main code is here:
var selector = "@(ul li)";
var jqSelector = selector.substring(2, selector.length - 1);
var components = $(jqSelector);
var ids = [];

console.time('Native Loop');
var length = components.length;
for(var i=0; i < length; i++) {
    ids[length] = $(components[i]).attr('id');
}
console.timeEnd('Native Loop');

console.time('jQuery Each');
components.each(function() {
    ids.push($(this).attr('id'));
});
console.timeEnd('jQuery Each');
My Firefox 11 shown (average time):

Native Loop : 28 ms
jQuery Each : 37 ms

IE8 shown:

Native Loop : 249 ms
jQuery Each : 281 ms

After that I deleted $ around components[i] in the for loop and replaced $.attr('id') by native .getAttribute('id') (what I always use in my not jQuery / JSF apps). Changes:
var length = components.length;
for(var i=0; i < length; i++) {
    ids[length] = components[i].getAttribute('id');
}
Look this test page please. Now we have in Firefox 11:

Native Loop : 3 ms
jQuery Each : 42 ms

and in IE8:

Native Loop : 14 ms
jQuery Each : 274 ms

Perfomance benefit in IE8 (with choosen selector) is 260 ms. Not bad. This trick can give more performance optimization in a huge page. I'm not a game developer and don't develop critical web applications. But a performance optimization is always good for me anyway. Optimization means not only CSS and JavaScript optimization. Loading of images / icons can be optimized as well. Next post(s) will cover more such stuff.

Sunday, January 1, 2012

New release of web resource optimization plugin

I have released a new 0.3 version of the Maven plugin for web resource optimization. As I mentioned in the last posts this plugin was created as a part of the PrimeFaces Extensions project. It produces better compression results than YUI Compressor and has some nice features. The current release fixes only one issue. Release notes are here. The plugin is available in the Maven central repository.

If you have any questions regarding to the configuration, ask me please in the PrimeFaces Extensions forum. This forum is also a good place for all questions to the components and more. Unfortunately, but PrimeFaces lead doesn't like to see any discussions related to our extensions in the main PrimeFaces forum. He considers such topics as advertisement and locks / removes them. That hurts and is weird because if it would be an advertisement, it would be an advertisement for PrimeFaces. We have "PrimeFaces" in the name "PrimeFaces Extensions". The aim was never to do an advertisement or get money. This project is just for fun, everybody can participate in.

Currently we are working on the last use cases for our showcase and plan to do a release in the middle of January. Next releases will be published at frequent intervals and include less stuff - approximately 2-4 new components, client behaviors, converters or similar JSF 2 related artefacts. Some stuff is amazing, so stay tuned.

Best wishes for the New Year!

Friday, December 30, 2011

Efficient component tree traversal in JSF

Everybody knows about findComponent() and invokeOnComponent() methods in JSF to find a component and doing something with it. The first method expects a special search expression and the second one component's clientId. They belong to UIComponent class, so that any UIComponent can acts as a start point in the view hierarchy. But what is about if we want to find many components at some start point in the view hierarchy which match certain conditions? We can apply getChildren() rekursive, but we wish us a convenient method for tree traversal. Tree traversal refers to the process of visiting each node in a component tree data structure. There is an efficient method in JSF accomplishing this task - visitTree()
public boolean visitTree(VisitContext context, VisitCallback callback)
context is an instance of VisitContext class that is used to hold state relating to performing a component tree visit. callback is an instance of VisitCallback whose visit method will be called for each node visited. Let's start with a practical example. Our task is to find and gather all components implementing EditableValueHolder. Such components implement resetValue() method which allows to reset component's submitted, locale values, etc. to an un-initialized state. Furthermore, another requirement is to skip sub-tree traversal for a component which should be not rendered (don't visit sub-components). In other words we want to find only editable components to be rendered. Assume, the start component calls target
UIComponent target = ...
It can be got in an action / event listener by event.getComponent() or somewhere else by findComponent().

We are ready now to create a special EditableValueHoldersVisitCallback in order to find all mentioned above sub-components and call visitTree on the target component with this callback. EditableValueHoldersVisitCallback gathers sub-components we want to reset.
EditableValueHoldersVisitCallback visitCallback = new EditableValueHoldersVisitCallback();
target.visitTree(VisitContext.createVisitContext(FacesContext.getCurrentInstance()), visitCallback);

// iterate over found sub-components and reset their values
List<EditableValueHolder> editableValueHolders = visitCallback.getEditableValueHolders();
for (EditableValueHolder editableValueHolder : editableValueHolders) {
    editableValueHolder.resetValue();
}
Callback looks like this one
public class EditableValueHoldersVisitCallback implements VisitCallback {

    private List<EditableValueHolder> editableValueHolders = new ArrayList<EditableValueHolder>();

    @Override
    public VisitResult visit(final VisitContext context, final UIComponent target) {
        if (!target.isRendered()) {
            return VisitResult.REJECT;
        }

        if (target instanceof EditableValueHolder) {
            editableValueHolders.add((EditableValueHolder) target);
        }

        return VisitResult.ACCEPT;
    }

    public List<EditableValueHolder> getEditableValueHolders() {
        return editableValueHolders;
    }
}
Result VisitResult.REJECT indicates that the tree visit should be continued, but should skip the current component's subtree (remember our requirement?). VisitResult.ACCEPT indicates that the tree visit should descend into current component's subtree. There is also VisitResult.COMPLETE as return value if the tree visit should be terminated.

Some components extending UINamingContainer override the behavior of visitTree(). For instance, UIData overrides this method to handle iteration correctly.

Tuesday, December 27, 2011

Maven plugin for web resource optimization - advanced settings

In the last post I have introduced a new Maven plugin resources-optimizer-maven-plugin. This post is about two advanced features. Aggregation tag has a sub-tag subDirMode. This is an aggregation per sub-folder. Assume, JavaScript / CSS files are grouped by sub-folders which represent software modules. Resources of each module can be optimized separately in an easy way. As output we would have aggregated files per sub-folder. Names of aggregated files are the same as their folder names where they are placed. Files are aggregated in the lexicographic order. The following pictures demonstrate this approach.

Original source files below sub-folder keyfilter:


Aggregated file in target below sub-folder keyfilter:


This can be achieved with the following resources set
<resourcesSet>
    <includes>
        ...
        <include>keyfilter/**</include>
        ...
    </includes>
    <aggregations>
        <aggregation>
            <inputDir>...</inputDir>
            <subDirMode>true</subDirMode>
        </aggregation>
    </aggregations>
</resourcesSet>
The second feature is a preparation of uncompressed resources. Sometimes you have to build / deliver compressed and uncompressed resources. In JSF you can use then uncompressed resources if ProjectStage is "Development". RichFaces has e.g. this handy feature. resources-optimizer-maven-plugin allows to define several aggregation tags, e.g. one for compressed and one for uncompressed resources. The following picture demonstrates this approach.

Two folders, for compressed (primefaces-extensions) and uncompressed (primefaces-extensions-uncompressed) resources:


That can be achieved with this resources set
<resourcesSet>
    <includes>
        ...
    </includes>
    <aggregations>
        <aggregation>
            <inputDir>${resources.dir.compressed}</inputDir>
            ...
        </aggregation>
        <aggregation>
            <withoutCompress>true</withoutCompress>
            <inputDir>${resources.dir.uncompressed}</inputDir>
            ...
        </aggregation>
    </aggregations>
</resourcesSet>

<properties>
    <resources.dir.compressed>
        ${project.build.directory}/classes/META-INF/resources/primefaces-extensions
    </resources.dir.compressed>
    <resources.dir.uncompressed>
        ${project.build.directory}/classes/META-INF/resources/primefaces-extensions-uncompressed
    </resources.dir.uncompressed>
</properties>
Output directory for uncompressed resources should be created first. Put maven-resources-plugin with phase generate-resources in front of resources-optimizer-maven-plugin (phase prepare-package).
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-resources</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <outputDirectory>${resources.dir.uncompressed}</outputDirectory>
                <resources>
                    <resource>
                        <directory>${project.basedir}/src/main/resources/META-INF/resources/primefaces-extensions</directory>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>
These were examples for an JAR project. The same is also valid for WAR (web) projects of course.

Monday, December 19, 2011

New Maven plugin for web resource optimization

Two months ago I released the first version of a new Maven plugin for web resource optimization. This plugin was created as a part of the PrimeFaces Extensions project. What is the PrimeFaces Extensions project? Thomas Andraschko and me have launched this young project with the aim of extending JSF library PrimeFaces. What does extending mean? We don't have "extends SomePrimeFacesComponent" in the code. It doesn't make sense to copy-&-paste or overwrite existing PrimeFaces code. PrimeFaces is a rapidly evolving component set and costs to maintain the entire code from release to release would be too high. Extending means, we use core functionality of PrimeFaces like core.js and CoreRenderer.java. Well. What for components and other stuff we have is not the topic of this post. This is a topic for next post(s). I just would like to appeal to everybody having JSF / PrimeFaces expert knowledge to contact us. Any help would be appreciated. We have great ideas and plans, but Thomas and me are full time worker and involving in various daily projects, so that time for PrimeFaces Extensions is very sparse. Even worse in my case. I can only work 15-20% for JSF in my daily work currently. So, everybody with experience in JSF / PrimeFaces can join this open source project.

Maven plugin for resource optimization can compress and merge JavaScript and CSS files very efficiently. It produces better results than all plugins I know. The new Maven plugin combines Google Closure Compiler (for JavaScript files) and YUI Compressor (for CSS files). The new plugin is highly configurable and allows some nice features which don't exist in other plugins. I would like to mention some highlights:
  • Flexible resource sets describing resources to be processed.
  • Settings for compilation and warning levels for Google Closure Compiler. Defaults are SIMPLE_OPTIMIZATIONS and QUIET.
  • Aggregation with or without compression.
  • Suffix for compressed / aggregated files if needed.
  • SubDirMode for files aggregation. Resources of each software module can be optimized separately in an easy way. It makes sense e.g. for component / widget development because you can say "merge files for component A to one big file and don't merge files for component B".
  • Possiblity to define a file to be prepended to the aggregated file.
  • Possiblity to build compressed and uncompressed resources at the same time. PrimeFaces community already asked about uncompressed resources for development stage. RichFaces and some other libs can deliver uncompressed resources if the ProjectStage is "Development". We have also done this for PrimeFaces Extensions by means of this plugin. A special JSF ResourceHandler can stream down uncompressed resources to the browser for the ProjectStage "Development". Never crypto-messages like "e is undefined" anymore!
I have tried to write a more or less comprehensive documentaion. Simple check it! We already use this plugin with success in 6-8 JAR and WAR projects. I have also drawn a comparison diagram for PrimeFaces: size in bytes without compression, with yuicompressor-maven-plugin and with our resources-optimizer-maven-plugin. And I have prepared a configuration for PrimeFaces to make changes easy. More details in the online documentation. We would be glad to see the resources-optimizer-maven-plugin in PrimeFaces! It's worth. This plugin is available in the Maven central repository. In the meantime I have released a new 0.2 version. Feedback is welcome. Thanks.

The next Maven plugin I'm planning to write is a CDK (component development kit) for PrimeFaces components (low prio, depends on free time). PrimeFaces has already one, but only for internal use. Futhermore, PrimeFaces's plugin doesn't generate component's source files under source folder (they are not under version control) and has an expensive configuration. The new CDK will be configurable via name conventions and avoid expensive configuration. The technique for that will be Java Emitter Templates (JET) from Eclipse Modeling Framework. Here is again - every help is appreciated. We have some code styles, so that our code is clean and optimized. But it's not a problem at all to follow them, even in a remote team. I'm convinced, the work in a distributed team can be very efficient.