Journal tags: pjax

2

A question of timing

I’ve been updating my collection of design principles lately, adding in some more examples from Android and Windows. Coincidentally, Vasilis unveiled a neat little page that grabs one list of principles at random —just keep refreshing to see more.

I also added this list of seven principles of rich web applications to the collection, although they feel a bit more like engineering principles than design principles per se. That said, they’re really, really good. Every single one is rooted in performance and the user’s experience, not developer convenience.

Don’t get me wrong: developer convenience is very, very important. Nobody wants to feel like they’re doing unnecessary work. But I feel very strongly that the needs of the end user should trump the needs of the developer in almost all instances (you may feel differently and that’s absolutely fine; we’ll agree to differ).

That push and pull between developer convenience and user experience is, I think, most evident in the first principle: server-rendered pages are not optional. Now before you jump to conclusions, the author is not saying that you should never do client-side rendering, but instead points out the very important performance benefits of having the server render the initial page. After that—if the user’s browser cuts the mustard—you can use client-side rendering exclusively.

The issue with that hybrid approach—as I’ve discussed before—is that it’s hard. Isomorphic JavaScript (terrible name) can theoretically help here, but I haven’t seen too many examples of it in action. I suspect that’s because this approach doesn’t yet offer enough developer convenience.

Anyway, I found myself nodding along enthusiastically with that first of seven design principles. Then I got to the second one: act immediately on user input. That sounds eminently sensible, and it’s backed up with sound reasoning. But it finishes with:

Techniques like PJAX or TurboLinks unfortunately largely miss out on the opportunities described in this section.

Ah. See, I’m a big fan of PJAX. It’s essentially the same thing as the Hijax technique I talked about many years ago in Bulletproof Ajax, but with the new addition of HTML5’s History API. It’s a quick’n’dirty way of giving the illusion of a fat client: all the work is actually being done in the server, which sends back chunks of HTML that update the interface. But it’s true that, because of that round-trip to the server, there’s a bit of a delay and so you often end up briefly displaying a loading indicator.

I contend that spinners or “loading indicators” should become a rarity

I agree …but I also like using PJAX/Hijax. Now how do I reconcile what’s best for the user experience with what’s best for my own developer convenience?

I’ve come up with a compromise, and you can see it in action on The Session. There are multiple examples of PJAX in action on that site, like pretty much any page that returns paginated results: new tune settings, the latest events, and so on. The steps for initiating an Ajax request used to be:

  1. Listen for any clicks on the page,
  2. If a “previous” or “next” button is clicked, then:
  3. Display a loading indicator,
  4. Request the new data from the server, and
  5. Update the page with the new data.

In one sense, I am acting immediately to user input, because I always display the loading indicator straight away. But because the loading indicator always appears, no matter how fast or slow the server responds, it sometimes only appears very briefly—just for a flash. In that situation, I wonder if it’s serving any purpose. It might even be doing the opposite to its intended purpose—it draws attention to the fact that there’s a round-trip to the server.

“What if”, I asked myself, “I only showed the loading indicator if the server is taking too long to send a response back?”

The updated flow now looks like this:

  1. Listen for any clicks on the page,
  2. If a “previous” or “next” button is clicked, then:
  3. Start a timer, and
  4. Request the new data from the server.
  5. If the timer reaches an upper limit, show a loading indicator.
  6. When the server sends a response, cancel the timer and
  7. Update the page with the new data.

Even though there are more steps, there’s actually less happening from the user’s perspective. Where previously you would experience this:

  1. I click on a button,
  2. I briefly see a loading indicator,
  3. I see the new data.

Now your experience is:

  1. I click on a button,
  2. I see the new data.

…unless the server or the network is taking too long, in which case the loading indicator appears as an interim step.

The question is: how long is too long? How long do I wait before showing the loading indicator?

The Nielsen Norman group offers this bit of research:

0.1 second is about the limit for having the user feel that the system is reacting instantaneously, meaning that no special feedback is necessary except to display the result.

So I should set my timer to 100 milliseconds. In practice, I found that I can set it to as high as 200 to 250 milliseconds and keep it feeling very close to instantaneous. Anything over that, though, and it’s probably best to display a loading indicator: otherwise the interface starts to feel a little sluggish, and slightly uncanny. (“Did that click do any—? Oh, it did.”)

You can test the response time by looking at some of the simpler pagination examples on The Session: new recordings or new discussions, for example. To see examples of when the server takes a bit longer to send a response, you can try paginating through search results. These take longer because, frankly, I’m not very good at optimising some of those search queries.

There you have it: an interface that—under optimal conditions—reacts to user input instantaneously, but falls back to displaying a loading indicator when conditions are less than ideal. The result is something that feels like a client-side web thang, even though the actual complexity is on the server.

Now to see what else I can learn from the rest of those design principles.

Async, Ajax, and animation

I hadn’t been to one of Brighton’s Async JavaScript meetups for quite a while, but I made it along last week. Now that it’s taking place at 68 Middle Street, it’s a lot easier to get to …seeing as the Clearleft office is right upstairs.

James Da Costa gave a terrific presentation on something called Pjax. In related news, it turns out that the way I’ve been doing Ajax all along is apparently called Pjax.

Back when I wrote Bulletproof Ajax, I talked about using Hijax. The basic idea is:

  1. First, build an old-fashioned website that uses hyperlinks and forms to pass information to the server. The server returns whole new pages with each request.
  2. Now, use JavaScript to intercept those links and form submissions and pass the information via XMLHttpRequest instead. You can then select which parts of the page need to be updated instead of updating the whole page.

So basically your JavaScript is acting like a dumb waiter shuttling requests for page fragments back and forth between the browser and the server. But all the clever stuff is happening on the server, not the browser. To the end user, there’s no difference between that and a site that’s putting all the complexity in the browser.

In fact, the only time you’d really notice a difference is when something goes wrong: in the Hijax model, everything just falls back to full-page requests but keeps on working. That’s the big difference between this approach and the current vogue for “single page apps” that do everything in the browser—when something goes wrong there, the user gets bupkis.

Pjax introduces an extra piece of the puzzle—which didn’t exist when I wrote Bulletproof Ajax—and that’s pushState, part of HTML5’s History API, to keep the browser’s URL updated. Hence, pushState + Ajax = Pjax.

As you can imagine, I was nodding in vigourous agreement with everything James was demoing. It was refreshing to find that not everyone is going down the Ember/Angular route of relying entirely on JavaScript for core functionality. I was beginning to think that nobody cared about progressive enhancement any more, or that maybe I was missing something fundamental, but it turns out I’m not crazy after all: James’s demo showed how to write front-end code responsibly.

What was fascinating though, was hearing why people were choosing to develop using Pjax. It isn’t necessarily that they care about progressive enhancement, robustness, and universal access. Rather, it’s often driven by the desire to stay within the server-side development environment that they’re comfortable with. See, for example, DHH’s explanation of why 37 Signals is using this approach:

So you get all the advantages of speed and snappiness without the degraded development experience of doing everything on the client.

It sounds like they’re doing the right thing for the wrong reasons (a wrong reason being “JavaScript is icky!”).

A lot of James’s talk was focused on the user experience of the interfaces built with Hijax/Pjax/whatever. He had some terrific examples of how animation can make an enormous difference. That inspired me to do a little bit of tweaking to the Ajaxified/Hijaxified/Pjaxified portions of The Session.

Whenever you use Hijax to intercept a link, it’s now up to you to provide some sort of immediate feedback to the user that something is happening—normally the browser would take care of this (remember Netscape’s spinning lighthouse?)—but when you hijack that click, you’re basically saying “I’ll take care of this.” So you could, for example, display a spinning icon.

One little trick I’ve used is to insert an empty progress element.

Normally the progress element takes max and value attributes to show how far along something has progressed:

<progress max="100" value="75">75%</progress>

75%

But if you leave those out, then it’s an indeterminate progess bar:

<progress>loading...</progress>

loading…

The rendering of the progress bar will vary from browser to browser, and that’s just fine. Older browsers that don’t understand the progress will display whatever’s between the opening and closing tags.

Voila! You’ve got a nice lightweight animation to show that an Ajax request is underway.