AJAX framework

From PKP Wiki
Jump to: navigation, search

Introduction and Credits

There are a few crucial design decisions to be made when implementing an AJAX framework. We want to especially credit the authors of http://ajaxpatterns.org/ as their site helped us immensely in thinking systematically about our AJAX design.

Client vs. Server Framework

We decided to implement a server-side framework mainly:

  • First of all we want to introduce AJAX gradually. We won't have an AJAX-only site any soon. Large parts of our applications will require full-page request/response cycles for a long time to come but will more and more be sprinkled with AJAX-driven components.
  • We want to re-use our existing know-how. Most of our developers are used to implement server-side applications. They know how to implement pages with PHP controllers and smarty views. We have much less JavaScript expertise than we know server-side technologies.
  • It is easier to maintain an application that is mainly written in one language. Tools that support PHP/smarty development are quite different from tools that support JavaScript development. We don't want to loose time by maintaining two separate tool sets.
  • Server-side frameworks keep most of the processing on the server while client-side frameworks offload some processing to the client thereby reducing server CPU load. Most typical PKP application installations are viewed by a moderate number of concurrent users and typically do not experience very strong access fluctuations. We therefore believe that in our case the advantages of a server-side design outweigh this disadvantage.

Semantic vs. HTML Data Payload

As we chose server-side processing as our general AJAX-approach, HTML payload is the logical consequence. We therefore decided to use HTML payload rather than passing semantic data (e.g. as XML) to the client.

We still may use semantic data payloads in specific use cases if we encounter requirements that force us to do so. This is especially the case where large data sets have to be transported to the client and manipulated there. Some performance relevant techniques (e.g. predictive fetch, XML data islands, etc.) work best with semantic data. Semantic data sets can improve usability and performance as data can be manipulated on the client without any need for network roundtrips.

XML vs. JSON vs. Plain Text Encoding

HTML can be transported over all three encodings. While plain text comes to mind first there are certain advantages in using XML or JSON even with an HTML payload. The advantage of a structured encoding is that you can send protocol data (e.g. status codes, etc.) together with the HTML payload.

We decided to wrap our data in JSON messages so we can send status messages along with the payload:

  • We prefer JSON over HTML as it can be directly parsed as JavaScript and uses less processing power on the client side.
  • JSON has a low memory and CPU footprint on the server side.
  • There is less format interference between JSON and HTML than between XML and HTML. In other words: JSON messages with an HTML payload need less escaping and are therefore easier to read for the human eye.

We might use XML encoding for semantic data if we need it in the future (see the comment on semantic data in the previous section).

Browser XSLT vs. Templating

The reasons to use HTML payload, JSON encoding and server-side processing have already been laid out. This means that we cannot use client-side XSLT. We'll use server-side smarty templating instead.

REST-style vs. RPC-style Calls

Server-side AJAX calls go over HTTP. This means that server-side controller methods need to to be triggered over URLs requested over HTTP. REST-style calls are considered simpler and "cleaner" by some. They are modeled closely along features of the HTTP protocol. REST-style messages come to mind naturally when thinking of simple CRUD-style applications.

In our case, however, we believe that an RPC-style call schema is better suited:

  • Our application is not a simple CRUD application. Our handler operations cannot be cleanly mapped to HTTP's PUT/DELETE/POST/GET methods. This impedance mismatch between the REST protocol and our internal API is the main reason why we prefer an RPC-style call scheme. It allows us to map URLs directly to our internal API in an easy and obvious way.
  • We want to maintain maximum compatibility with a very large number of target installation environments. As some web servers do not support HTTP methods like PUT or DELETE we prefer to use an HTTP-to-handler-mapping that does not require "exotic" HTTP methods.
  • We do not plan to expose our API directly to end-users which would be a certain argument in favor of a (simple) REST-style approach. In other words: we are providing full end-user applications and not web services. Where we explicitly provide web-services we still might think of using REST where appropriate.

SOAP vs. XMLRPC vs. Client Stub vs. Procedural API

RPC-style APIs can be exposed via a variety of different technologies. We chose a simple procedural approach that maps URLs to handler operations.

JavaScript stubs that reproduce a server-side API on the client side are most helpful in a client framework. As most of our calls can be done from simple URLs, full client-side JavaScript stubs would introduce an unnecessary amount of code to be maintained on the client.

SOAP and XMLRPC calls are too complex for our simple requirements. We don't need to transport sophisticated data structures from the client to the server. The simple key-value approach of GET or POST requests can handle all we need. SOAP/XMLRPC would be over-engineered in our case.

The procedural API approach falls into place naturally. Please see our Router Architecture document for further details.

Performance-Relevant Design Patterns

Multi-Stage Download

We chose to employ multi-stage download where possible. This means downloading an HTML document to the client first that then triggers further network roundtrips to download components.

This has several advantages:

  • The perceived loading time is reduced as the first response comes in quicker and the user already has the basic page structure on screen.
  • The server-side framework we use supports multi-stage download well.
  • Multi-stage download decouples the page controller from the component controllers. The only thing that the page controller needs to be aware of is the RPC service endpoint (=URL) of the components it wants to include.

Predictive Fetch

Predictive fetch is a technology where the client decides to fetch more data from the server as currently needed to improve response time when the client needs the data later.

As we are using HTML payload and a server-side approach, predictive fetch cannot be used in our case (or is at least very difficult to use).