My Blog has moved to Github Pages

Sunday 30 January 2011

Progressive Enhancement with GWT, part 1

This is the first part in a series, following my thoughts on using GWT in SEO'able web applications. The other parts in the series are part 2 and part 3.

GWT Is a superb framework for developing complex, componentized html & javascript widgets.  You can have your cake and eat it:
  • Drop down into native javascript as and when you feel the need
  • Integrate easily with native js components and libraries
  • Use GWT components relatively easily from native javascript
  • Create super-condensed, fast, platform-specific code, easily
  • All the benefits of Java's static type-system, packages, and tooling to manage and refactor your code
It is very tempting to go for an all-out GWT user-interface, which is great if what you want is a super-snazzy Rich-Internet-Application which packs down into very small and extremely cacheable js bundles that fetch data asynchronously from the server, and you don't mind re-compiling your user-interface to make even a very small change.

It isn't so great when:
  • You need to expose the content of your site for search-engines to index (The SEO Problem).
  • You want to leverage the html and css skills of your UI designers, and to be able to generate more flexible layouts without requiring a re-compile (The Design Problem).

The SEO Problem

To a search engine, GWT apps just look like a big fat lump of dense javascript. Nothing to see here, move along. Its a similar problem for any web-app that uses ajax to collect data from the server, but the problem is magnified with GWT due to the fact that the entire application tends to present as a large lump of dense javascript, whereas many other ajax technologies typically involve some amount of server-side content rendering that can make the site at least partially visible to crawlers.

Google have a recommendation for how to get around the problems of SEO for ajax applications, which entails a special url form and the creation of "html snapshots" - effectively a parallel, ajax-disabled site that the crawler can index. This seems to me to be a workable but irritating solution that involves doing a lot of extra work just to allow a search engine to crawl the site. Its effectively just a Google-approved cloaking method. Also it isn't clear to me whether any other search engines than Google support this approach.

The Design Problem

Don't get me wrong, its not as bad as all that. You can, of course, leverage your UI/UX designer's talents when building GWT apps. They can produce designs that the GWT developers base their components on, and with UIBinder the html fragments produced by a designer can be used in large chunks, but there is always some disconnect between what the designers produce and what is actually output by the application - usually because there is a developer translating the designer's work into GWT components.

In retrospect, having built a number of "monolithic" GWT applications, it seems to me that what we're missing is a way to step back just a little from the "GWT does everything" mind-set, and instead to leverage GWT where it is best suited, and something a little more flexible where GWT can be too restrictive - for example when laying out high level components on a page it would be advantageous to be able to escape from the restrictions of having to compile that page layout into js, and instead work at the level of straight-forward declarative markup.

Introducing "GWT-Activated Pages"

How can we solve these two issues? One idea I've been toying with, is to use GWT for progressive enhancement of simple html + css, and goes as follows:

Rather than try to build two almost parallel versions of your application (one for SEO, one for real users), why not build one with a layered approach that allows graceful degradation for browsers with javascript disabled (of which search-engines could be considered a sub-set).

The base-layer that non-javascript browsers would render, and which search-engines would see, would be generated  by some typical server-side technology - php, jsp, struts, jfaces, ... take your pick. This would build a "wireframe" of your page, giving it a basic shape and layout, and filling in some starter content. The markup would ideally be meaningful, in the sense that headings would appear in <h1> tags to indicate that they are headings, rather than to give them any particular styling.

This base layer would be something that designers could work on directly, including any and all css styling.

The second layer would be a set of GWT widgets that "activate" or progressively enhance the page, by scanning the DOM for certain signs that denote activateable sections of markup. When the base page loads, GWT widgets search for elements to bind themselves to. When a widget finds such an element it binds to it and "activates" it. Activation could mean anything from completely changing the html markup, to binding event-listeners, to handling interaction with ajax data loading from the server.

Here's a simple example "base" layer:


<html>
  <body>
    <h1>Page Header</h1>
    <ol class="gwt-navigation-widget">
      <!-- the listitems are generated server side -->
      <li><a href="..">Home</a></li>
      <li><a href="..">News</a></li>
      <li><a href="..">Videos</a></li>
      <li><a href="..">Photos</a></li>
      <li><a href="..">About</a></li>
    </ol>
    <ol class="gwt-news-ticker-widget">
      <!-- the listitems are generated server side -->
      <li>News story 1</li>
      <li>News story 2</li>
      ...
      <!-- this last listitem gives a link that a search engine can follow to get more data -->
      <li><a href="..">older stories</a></li>
    </ol>


    <script type="text/javascript" language="javascript" src="widgets/navigation-widget.js"></script>
    <script type="text/javascript" language="javascript" src="widgets/news-ticker-widget.js"></script>
  </body>
</html>

Notice the elements with css class-names prefixed with "gwt-". These are the signs that our gwt widgets will be looking for in order to know which elements they should activate.

As you probably guessed, the navigation widget would detect any elements with a class-name matching "gwt-navigation-widget", while the news-ticker will search for "gwt-news-ticker-widget".

OK, so what do we get for our troubles? Well, several things potentially:
  1. One request to the server to get our initial page full of data (rather than multiple widgets requesting async loading of little chunks of data)
  2. A page that contains the data and is search-engine friendly, allowing pages deep within your app to indexed by search-engines
  3. A very clear separation of widgets and page layout, allowing you more flexibility to change the page layout without GWT re-compile
  4. Flexibility in dividing work between designers and developers:
    • designers can focus on the design-heavy html and css work, and the overall page layout
    • developers can focus on interaction with the server, complex widget behaviour, etc.
Upon finding an element to bind to, the widget would:
  • Examine the content of the element - this will very likely be the source of its initial configuration and/or data-set, and also might include some information about how to load more content, as in the news-ticker example whose last <li> is a link to "older stories". I'm sure it would be a good idea to make this even more explicit, but like I said this is supposed to be a simple example :)
  • Replace or modify the content of the element - perhaps the widget displays a very complicated UI, so it removes the html and replaces it with something nifty that it generates, or maybe it just adds some decoration in the form of small visible changes, or perhaps it binds a bunch of event handlers to do neat tricks like adding gesture handling for touch-screen users.
It seems that it would be perfectly possible to bind widgets inside widgets in this way, although at some point you would probably want to control the binding order such that an outer widget binds before an inner one. One way to do this might be to have a page-activator that seeks elements that want to be activated, and which all widgets are registered with. This could be described nicely as a Pattern.

In my simple example I showed the scripts being loaded separately, just for clarity, but I'm sure you wouldn't want to load each widget as a separate script - that would lose a good chunk of GWT's advantage. Rather, the whole widget-set could be loaded as one script, cached forever, and used all over.

Now, if you want to see an example of GWT-activated pages at work, just take a look at my older post on rendering 3D Rubiks Cubes with GWT and HTML5 Canvas, where the rubik's cubes are rendered by a gwt widget that "activates" a <div> element containing the configuration for the cube.
OK, but what are the down-sides? Here's a few...
  • Compiler no longer has visibility across the whole UI.
  • Messaging between components becomes more difficult (but not impossible). This has its advantages too - it forces low coupling. Messaging via OpenAjax Hub or similar would be worth considering.
  • It's more work than a straight-out GWT UI, and many would argue why bother to use GWT at all if you need SEO (depends on your skill-set and the complexity of the components you're building in my view).
  • I'm sure that there are others which I'm currently blind to ... I need to try to build some more complex and interesting examples to find these out.

tl;dr ?

Monday 17 January 2011

Reading List, 17-01-2011

I love it when I get a box from Amazon. Today's new arrivals: five (count 'em) new tech books:












I'm particularly intrigued to read "The Art of Scalability" - I've never come across a book quite like this that addresses the organisational aspects of scaling a company and processes alongside the architectural aspects of developing scalable software.

Monday 3 January 2011

Linux Distro popularity

Interesting to see how Ubuntu has overtaken its sire Debian in recent years - Google Trends really is amazing.

Google Trends chart of Ubuntu (blue), Debian (red), CentOS (green) and Suse (orange).
Here's the link to see the full google-trends page for this comparison.

I love the spikes on the ubuntu line every 6 months - I imagine these coincide with the 6-monthly .4 and .10 releases (April and October).

Interestingly, when I compare Ubuntu with Windows 7 and OSX, OSX loses out strongly to Ubuntu (perhaps I'm using the wrong term, but I tried a number of different combinations), while Win7 is around 3x more popular than Ubuntu.  Also interesting to note how OSX beats Ubuntu in the "news" mentions (below the x-axis) presumably because of the Apple PR machine:

Google Trends chart of Ubuntu (blue), Windows 7 (red), OSX (orange)

Sunday 2 January 2011

3D graphics using the html5 canvas


I thought i'd put up a quick sample of my latest play-thing - a 3D rendering of a rubik's cube, using javascript (GWT) to implement the z-buffer and the html5 canvas as the display.  I originally built this in plain old javascript, but have now converted it to GWT - partly just for fun and partly to make the code a bit more manageable and refactorable (if that's even a word). Along the way I made a few optimisations like caching radian, sin and cosine values of angles.

The cube is made from 27 "blocks", each of which has a face in each of the rubik-cube face colours. When the 27 blocks are put together we get the completed cube. Admittedly the 27th block isn't really necessary (its right in the middle where it is never visible), but it made life just that little bit simpler to ignore that and go with it.

The cubes you can see below are rendered when the page loads. The scenes are pretty simple, so render very quickly. You may have seen the cube configuration instead of the cubes for a short while until the javascript loaded, at which point the configuration is replaced by the rendered cubes.

Configuring a cube to display is as simple as adding a <div> element like this:

<div class="rubiks" style="width:150px; height:150px;">
  {"rubik-cube":{}, "camera":{}}
</div>

This sets up the default position and orientation for both camera and cube, which looks like this:
{ "rubik-cube": {}, "camera":{} }
That's a pretty boring view, so lets rotate the cube so that we can see more than just the red-face nearest us. To do that we supply some rotations around the x and y axis like this:

<div class="rubiks" style="width:150px; height:150px;">
  { 

    "rubik-cube":{ 
      "rotate-x":35, 
      "rotate-y":35, 
      "rotate-z":35 
    }, 
    "camera":{}
  }
</div>

This results in the following cube:
{ "rubik-cube": { "rotate-x":35, "rotate-y":35, "rotate-z":35 }, "camera":{} }
I'm quite pleased with the results so far, and the performance is not bad either it seems. The speed of actually drawing on the canvas seems to be plenty good enough to get away with a bit of animation. On my (Core i7) laptop I can spin the cube on all 3 axis at a couple-hundred frames per second (hopefully i'll put up an example in a later post).

Next steps for the rubik's application (yeah, like i'll get around to it) would be:
  • Supply "twist" information in the configuration so I can show cubes in various stages of completion.
  • Animate the twists, allowing a viewer to step through the twists, for example to see how to solve a particular part of a cube.
  • Interactive mode where the viewer can play with the cube.
In a separate direction, the z-buffer i've built up in order to render the cubes could be improved in lots of nice ways too.

Just before I finish off with a few more views of the cube, I wanted to mention that I had a few issues finding a way to host the scripts and use them in Blogger. Annoyingly you can't host javascript or html files directly from Blogger, so I had to find somewhere else to put them.

My usual approach for hosting source code is to use github "gists", which provides a neat way of showing prettified source, but also lets you view the "raw" source. That allowed me to host the js somewhere, but I had to work around a cross-site scripting issue loading the GWT sources from a different domain.

Fortunately GWT makes that easy with its "xs" linker, which produces a bunch of ".no-cache.js" files instead of "no-cache.html" files, and solves the XSS problem. To use the xs linker you just add a single line to your .gwt.xml file:

<add-linker name="xs" />

Sadly that prevents hosted mode from working (currently), but that's easy enough to work around :)

{ "rubik-cube": { "rotate-x":35, "rotate-y":35 }, "camera":{} }

{ "rubik-cube": { "rotate-x":45, "rotate-y":135 }, "camera":{} }

{ "rubik-cube": { "rotate-x":45, "rotate-z":135 }, "camera":{} }

{ "rubik-cube": { "rotate-x":45, "rotate-y":215 }, "camera":{} }

{ "rubik-cube": { "rotate-x":135, "rotate-y":35 }, "camera":{} }

{ "rubik-cube": { "rotate-x":95, "rotate-y":125 }, "camera":{} }

{ "rubik-cube": { "rotate-x":15, "rotate-y":15, "rotate-z":15 }, "camera":{} }

{ "rubik-cube": { "rotate-x":25, "rotate-y":-25 }, "camera":{} }