webtier@glassfish.java.net

Re: [webtier] Optimize page load duration

From: Jim Driscoll <Jim.Driscoll_at_Sun.COM>
Date: Thu, 27 Aug 2009 11:00:00 -0700

On 8/27/09 6:17 AM, webtier_at_javadesktop.org wrote:
> Just an idea for (hopefully) upcoming JSF 2.1 ...

Please consider filing a feature request for Mojarra. I *think* what
you describe can be done without spec changes, but those may be required
as well.

> I digged a lot in the source solving the problem that inline javascript and onevent handlers on tags are not considered to be modern any more. Having google's best practises for website loading optimization (http://code.google.com/speed/articles/include-scripts-properly.html) in mind, all static javascript followed by inline javascript should be rendered right before body's closing tag and not in the head or in the middle of the page, because this slows down downloading of other resources (images, css, flash) significantly.

I hadn't read that article before, thanks: Though I suspect that you'll
find more for your consideration at Yahoo's site, they've got a great
writeup here:

https://developer.yahoo.com/performance/rules.html

I actually disagree with the emphasis of the Google article you pointed
to: The real problem isn't the lack of parallel loading, it's the load
itself, with latency times often crossing the 100ms ("hey, this is
slow") threshhold. While parallel processing would help, loading 5
files is always going to look slow to the user who's not on a LAN.

> I had two solutions in mind, both of them not perfect:
>
> 1) All inline javascript and event binding is done at the bottom of the body in an inline javascript block.

I've been coming to this conclusion as well.

> This could be done by rearranging inline js blocks like<h:outputScript target="body"> does and

Yes, I agree this would be the way to go. One problem - if the user
clicks on a button on first load, IT WON'T WORK RIGHT until the js
finishes loading. This can be a *severe* usability issue, and is the
one reason that I've held off from doing this. This problem must be
addressed as part of the solution, before we can implement this.

> render the event binding block explicitly by traversing the view another time using a component vistor which only render the js binding code.

We disagree here. It would be better to save the information on first
pass by dumping it into a map in the context. Tree traversal can get
pricey - you'd just be changing one problem for another.

> 2) Render the page without any js. Instead register a document.ready listener which fire an ajax request that traverse the view like in 1. but returns the inline js and binding code as<eval> response.

I really dislike this solution, preferring the previous one. It seems
considerably more fragile without a corresponding benefit in
performance, and would increase server load. It also makes the "early
click" problem worse, since the page load signal is no longer displayed
to the user.

> Both solutions are not perfect at all. The first one still embeds js code in the html page, even all js is rendered in one position.

Why do you believe that is bad? Honest question... It's my
understanding that this shouldn't effect the render time on the client.

> The second one requires an additional request to be sent, which has to wait until the required resource jsf.js was loaded.
As I said, it's unclear that it would what client-side benefit would
accrue, and it's quite clear that it would increase server load -
possibly significantly, since you're turning almost every xhtml request
into two requests by default...

> In addition we need to keep partial page rendering in mind. If we detach html elements and their event bindings we need to make sure that added elements during an ajax request will receive their bindings in an extra<eval> block.

That part is easy, compared to everything else. And we don't need to
use an eval block (which is painful for other reasons - we're rendering
inside an update, remember), we can inline the javascript in the
response now - it's not nearly the issue for partial updates that it is
for full updates.

> Suggestions and other possible solutions to avoid inline javascript and event binding are welcome.

Request aggregation would also be nice, and quite possibly a better
performance increase that what we've already been discussing - allowing
outputStylesheet and outputScript requests to be aggregated on the
server would be (somewhat) cheap on the server side (though potentially
expensive in disk space, with caching), and would eliminate a great deal
of network latency for the client. That, however, would probably
require a spec change, since you'd have to make it explicit in the tag
that aggregation was taking place. But since the user can now do this
manually, it's not clear to me that we necessarily have to add this...
I'm still thinking about it.

Jim