5.9. Performance

Yahoo published a list of best practices for improving web application performance.

Click Framework provides a PerformanceFilter which caters for some of these rules. However not all rules can be easily automated.

This section outlines how to apply some important rules which are not covered by the PerformanceFilter namely, Minimize HTTP Requests (by combining files) and Minify JavaScript and CSS.

The Rule, Minimize HTTP Requests, also mentions CSS Sprites, a method for combining multiple images into a single master image. CSS Sprites can boost performance when your application has many images, however it is harder to create and maintain. Note that CSS Sprites is not covered here.

It is worth pointing out that its not necessary to optimize every page in your application. Instead concentrate on popular pages, for example a web site's Home Page would be a good candidate.

There are a couple of tools that are useful in applying the rules "Minimize HTTP Requests" and "Minify JavaScript and CSS":

Below are some articles outlining how to use YUICompressor and Ant to concatenate and compress JavaScript and CSS files:

Using one of the approaches above you can concatenate and compress all JavaScript and CSS for your Pages into two separate files, for example home-page.css and home-page.js. Note that the two files must include all the JavaScript and CSS that is generated by the Page and its Controls. Then you can instruct Click to only include the two compressed files, home-page.css and home-page.js.

Click makes use of the utility class PageImports to include the CSS and JavaScript. PageImports exposes the method setInitialized(boolean), which controls when PageImports are fully initialized. Once PageImports have been initialized, no other CSS and JavaScript will be included.

Knowing this one can override Page.getPageImports(), and import the necessary JavaScript and CSS files and then set PageImports to initialized, forcing PageImports to skip other CSS and JavaScript files.

Here is an example:

public class HomePage extends Page {

    private Form form = new Form("form");

    public void onInit() {
        form.add(new EmailField("email");
        addControl(form);
    }

    public PageImports getPageImports () {
        PageImports pageImports = super.getPageImports();

        // Add the Page Css to the PageImports
        pageImports.add(new CssImport("/assets/css/home-page.css"));

        // Add the Page JS to the PageImports
        pageImports.add(new JsImport("/assets/js/home-page.js"));

        // Set pageImports to initialized so that no other Css and JavaScript
        // files will be included.
        pageImports.setInitialized(true);
        
        return pageImports;
    }
}

Using the following border-template.htm:

<html>
  <head>
    <title>Click Examples</title>
    ${headElements}
  </head>
  <body>

  ...

  ${jsElements}
  </body>
</html>

the rendered HTML will include one CSS and one JavaScript import:

<html>
  <head>
    <title>Click Examples</title>
    <link type="text/css" rel="stylesheet"
          href="/click-examples/assets/css/home-page.css" title="Style"/>
  </head>
  <body>

  ...

  <script type="text/javascript" src="/click-examples/assets/js/home-page.js"></script>
  </body>
</html>

A live demo is available here