This is my personal blog. The views expressed on these pages are mine alone and not those of my employer.

Saturday, January 14, 2006

AJAX/DHTML Tutorial: Should I Render My UI On The Server or the Client?

I want to share a bit about the different kinds of AJAX/DHTML architectures that are involved in creating a large scale AJAX application, and the dangers of choosing an incorrect one.

In general, large scale AJAX applications involve a Model-View-Controller (MVC) architecture; the primary difference is where each of these pieces are rendered and live:

1) Thick Client - everything on the client - In this architecture, the client has a representation of the system (the model); has a way to generate a view using this model; and has a controller that can mediate instantiating and saving the model from remote web services. All of these pieces exist on the client, and are created using JavaScript, HTML, CSS, optional client-side XSLT, etc. The server-side becomes a simple set of APIs, exposed as RESTian endpoints, XML-RPC, etc., which can return XML, JSON, etc. Frameworks like Dojo and JSON can help with creating these kinds of systems.
2) Thin Client - simply a controller - In this architecture, the client side simply has a controller that can capture user events, like mouse clicks; as the user interacts with the UI, the controller fetches the rendered UI from the server. The server actually renders the appropriate UI, where the View and Model live, and returns HTML that is dynamically inserted into the UI using innerHTML. Ruby on Rails facilitates this kind of programming, as does Prototype.

The Thick Client approach moves most of the software engineering to the client; it's weaknesses are that it is a new environment for server-side programmers, many of whom don't respect JavaScript or the level of software engineering it can require to produce quality results. It is difficult to find DHTML programmers who know how to work within this environment. It's strengths are that if done right, it can create a far better, more performant UI experience than the Thin Client. Examples of UI's built as Thick Clients are the Google RSS Reader and Jot's Tracker.

The Thin Client approach can be used with server-side abstraction libraries, like Ruby on Rails, so it can be leveraged quicker. It's strength is that it builds on familiar and available server-side skills, and can sometimes be used to leverage an existing system. However, as your application becomes more sophisticated, it's performance will begin to degrade significantly, since every action will require a full round trip to the server to render the HTML, return it, and then insert it into the page.

The reason for this post was to highlight the dangers with the Thin Client, having the view and model rendered on the server side. If the reason you chose AJAX and DHTML in your project are to have something that feels blazing fast, and if your application is sophisticated, you would do well to stay away from the Thin Client approach.

I was recently playing around with News Alloy, a full featured RSS Aggregator and Reader built using AJAX/DHTML (Disclosure: I consult with a competitor, named Rojo). I was wondering why it felt so slow; every time I would click to a new section, such as clicking the Manage tab to add a new feed, a little red "Loading..." indicator would appear. Things felt sluggish.

I decided to boot up Live HTTP Headers to watch the network traffic, and quickly found that every UI action was forcing a call to the server to render the new UI.

For example, when I click the Manage tab, the News Alloy page does a silent background call to two URLs:

If you go to these addresses yourself in your browser, if you are signed in, you will see that they actually return the rendered Manage tab as HTML, embedded in JavaScript. This is why the entire UI feels sluggish; it's almost like an X Windows UI, since every call forces the view to be rendered on the server side.

In general, if your UI is very simple (such as the one's produced by 37 Signals, like Ta-da List), then the Thin Client approach can be valid. However, once you pass beyond a certain threshold of application sophistication, if you don't take the Thick Client approach you will end up creating something that feels too slow.

Keep in mind, however, that the Thick Client is itself not magic pixie dust; you must still architect your application intelligently, choosing proper caching strategies and optimizing bottlenecks, in order to have good UI performance.

Also, there are no silver bullets; if you are in a situation where you have a simple UI with a minimal amount of AJAX, or where performance is less important than rapid application development or leveraging existing asserts, consider the Thin Client approach.

Excellent article Brad.

I prefer the thick client like in qooxdoo because some complex UI things could not be resolved on server side.

For example you have no possibility to get the font sizes of the client. If you do these things on the client, you can calculate the "preferred" dimensions of labels easily to generate the matching layout around these labels.

qooxdoo for examples support such "auto" modes where is renders the complete UI (even complex stuff) without any complex HTML (like tables) as so needs some informations to handle things like text. In qooxdoo we does generate the UI completly with absolute positioned divs. It is really hard to move these complex stuff to the server, because the server is just not a browser and cannot do some offsetWidth calculation of a DIV element.
Very good article indeed. As boundaries between architectures are a big melding pot at the moment, there are of course always a gray zone where applications can break new middle ground somewhere in-between since the coming of XMLHttpRequest.

For instance, I have been working with a thin client one-page set top box interface in recent months, where the traffic between client and server is just the bare JSON necessities to let the client render a new rich interface view, in effect navigating a huge menu system full of movies, trailers, services and whatnot. It's essentially a minimal subset of semantic markup for menus and forms, encoded in JSON, which the persistent client interface renders into HTML views.

All application logic lives server side, but it's a greased weasel for never having to bother with layout, or wasting bandwidth on *ML markup overhead.
Great article Brad. I have a framework that I've written called YAJAF! that I've been trying to get some feedback on. My framework is basically an internal tool for another project I'm working on, and I was soliciting feedback to see if there was any interest in it, so far not really.

I think the real key to this whole Web application thing is more robust tools on the client side. The 'render everything on the back end' approach just isn't scalable and severely limits what you can and can't do with your application.

I was like the people you mention in your article, I didn't really respect javascript. Then upon looking into the language more deeply, I found that it's actually quite robust (although very quirky). I've started writing little "lessons in javascript" at the YAJAF! blog to try and share this. It's amazing how languages can be stereotyped (look at lisp).

My objective of the YAJAF! framework was to leverage the experience people have with traditional programming methods to be able to make web GUI's.

For example, if I want to make a new window in an application I do something like this. (the library was originally called FX until I found out there are a ton of libraries with FX in the name, working on changing it).

//create a new "simple" window (with minimize, maximize, resize widgets)
// with a title, and a position of 100,100 and a size of 200,500
var myWindow = new YAJAF.FXWT.window.FXsimpleWindow("Title of Win",100,100,200,500);
var myPanel = new YAJAF.FXWT.FXpanel();
var myButton = new YAJAF.FXWT.FXbutton("Press Me!")


As you can see it looks (and acts) a lot like making a SWING GUI.

I have layout managers, a packaging system, and all sorts of other fairly advanced stuff in there (although I still haven't finished my lightweight scrollbars, sigh).

I haven't released this next bit but I've started taking screencasts of some of my sample applications, the first is a simple file browser. I haven't published any of it on the 'official blog' yet because vnc2swf makes the application look *a lot* choppier than it really is. I've been looking for a better solution to making a screencasts and haven't found one yet (that's free).
On the web, the thick client makes no sense at all.
I tried, which is precisely such a rich client, and newsalloy is about a thousand times faster.
The conclusions have no evidence whatsoever to back them up.
It's all assumption.
Mikael, thats why I said that neither approach is magic pixie dust. The thick client approach is hard to do right, and if you do it wrong or misapply it, you will result in something that is more sluggish. If you do it right, in some cases, you can have a more responsive app. There are no silver bullets.
mikepk, thanks for sharing your framework with me; I'll take a look at it.
I think this is first-and-foremost a discussion about system architecture and design patterns: depending on the situation you could gradually move more or less processing to the client. The same is true for data: how much data will you pre-load on the client, and how much will you load on-demand? As you mention, it depends on the type of application, but also on the audience. People on a dialup connection or people on a high-latency connection at the other side of the world will have different requirements. I guess you could write a book about this (and Michael is actually doing this :-).

Obviously, each toolkit has certain base principles, and Ruby on Rails is indeed more server-focused than Dojo. It's just my feeling that this difference will fade out. Dojo is now bundled with the WebWork server-side framework, Prototype gets more client-side functionality, and also the company I work for (Backbase) has launched server-side products in addition to its client-side AJAX framework.

By the way: I find the RSS Reader examples pretty disappointing, including Google RSS. But I don't really like Gmail either, so maybe it's just me. Although it's just a demo, you might want to take a look at the Backbase RSS reader, which has much more desktop-like features (more of a 'thick' client, if you wish).
Interesting (and timely) article--this is a topic that is getting a lot of interest.

One area that there has been little discussion on, is how additional features in the browser are making it an increasingly suitable 'thick client'. There are a number of standards that are starting to gain awareness, such as XForms and SVG. XForms is of particular interest to server-side programmers since it allows them to create Ajax applications using mark-up rather than script. XForms supplements XHTML by adding UI elements like 'hint' and 'help', rules for validity, and easy management of data submission to all sorts of end-points.

I've written an introductory tutorial that even in a few lines of mark-up shows rich messages, hiding and showing of controls, tooltips, context-sensitive help, saving data to and more.

There's also a full-functioning timesheet application that uses features like sliding panels and controls that shake when invalid. To get such features in their forms, authors just us simple CSS rules, again making it easy for server-side programmers to use without learning new languages.

The key point is that Ajax is implemented with standard mark-up and CSS rules, not script.
Thanks Brad for raising this issue which is, to me, on the critical for AJAX to enter the real life.
I fully support thin client approach and I developed a real-life AJAX catalog on this design.

My idea was: to make a web page behave like a Desktop Form, have a Desktop Form running on the server, make the web page as a "clone" of it, and let it take care of events.

Take a picture of the form before and after the event, figure out what has changed, build corresponding DOM instructions you send back as XML to client for execution.

This way you can :
- take advantage of RAD OOP environment
- be sure your client javascript is standard and really cross-browser
- lay out the form visually
- bring existing apps to AJAX

I just blogged an article on this approach: Ajax on-line Catalog(s): Ajax : Keeping Presentation Logic on Server. Hope you all will find it interesting !
I'm working on my first substantial AJAX application, partly for my own edification, and partly to pay the rent. :-)

One of the things I like the most about the AJAX approach is the loose coupling between the client and server sides that it imposes; Rather than forcing the server to keep track of everything the user does and sees (while the client sits there doing next to nothing besides displaying pages), I prefer the approach of letting the server simply "talk" to clients in XML that represents the information the clients need at a particular time, independent of its presentation. In an AJAX application, for me at least, this means that a thick client approach is the way to go: Let the client make the decisions about presentation and directing the traffic. I like how an AJAX application can be written so that markup language and CSS defines the UI's appearance, simple scripts define the UI's behaviour, and slightly more involved scripts play more of an "API" role to the UI-oriented stuff. Everything has a "this is how it should be" kind of feeling that way. The downside? Just this: I'm basically a server-side/API-type developer who's been doing development in C++, Java, Delphi, and other stuff for about 15 years. I used to hate JavaScript and all scripting languages because if you do something stupid, you don't know about it until runtime (no compiler). The remedy for this problem is to a) be more careful when writing code, b) look more closely at my code when getting ready to deploy and test, c) be more careful when writing code, and d) be more careful. Writing JavaScript has taken a bit of getting used to, but I'm finding it to be a cool little language.

So, yeah, I like the thick client approach. The idea of the server rendering the presentation just doesn't feel natural.
(in response to the comment on my blog)

Brad, what kind of XML description would you be interested in? Can you give me an example? What would be the primitive UI structures? (i.e. fundamental widgets like panels and sliders?)

I could make something like you describe, it might take a little work but since YAJAF is fully object oriented, pushing objects to the client would be perfectly natural. Maybe the intermediary 'language' could be json which might be easier to debug.

I have a lot of debugging tools built into the library to help out with this kind of thing as well.

I'm looking for some sample applications to promote this library/framework thing I've made. The intermediary XML->js language thing might be a nice feature to get server-side/thin client people interested.
Nice article. I had this question always and still there is not a good answer to this. Your article covers exactly this thing which comes across people's mind when they design their application using AJAX.

I have some questions related to it.
1) What is the maximum amount of data which should be generated by server side (thin client approach). I have a situation where in, i do get incremental amount of data and this is auto refreshing too (front end client). Recently i analyzed it and found that I am fetching around 9 MB of data. This made me feel shall i instead start implementoing thick client approach. For this i will need to first create XML judiciously , apply XSLT on the client and create html and present it. To get my data, i have to make query to the database and then form xml.

2) To get 9 MB of data from thin client approach it took me 55-60 seconds, will the other approach if done correctly provide me better result?

3) I have four frames in my front end and these needs to auto refresh the screen. I have made 3 frames which contains data and a triggering frame which polls the server for new updates and if it finds new update it triggers other frames to fetch data and these frames stops fetching data if they don't find any more updates.

Any other pointers to implement this requirement would be highly appreciated.

Post a Comment

Links to this post:

Create a Link

<< Home

This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]