Hybrid Web Applications

Preview:

DESCRIPTION

Can traditional document-based applications compete with the user experience frameworks such as Ember & Angular are known for?

Citation preview

Hybrid Web Applications with PJAX & HATEOAS

James Da Costa

@jamesdacosta james@bright-interactive.com

jamesdacosta.com

1885

2014

Hybrid Web Applications

An approach to improving the user experience of legacy web applications

Modernising applications in a way that doesn’t ignore the fundamental tenets of the web

Borrowing ideas and techniques from the old-school web and new technologies

BackgroundNeeded to rewrite a server-side application and

wanted a better UX

Decided to learn about client side SPA frameworks (Ember/Angular)

Realised there’s a steep learning curve

Big mindset shift from server-side to client-side development

Is there another way?

Retain server-side development environment

Fluid & engaging UX (like modern SPAs)

Not learn a big client-side framework

Imagebase - Upload, tag, and edit images

ToolsetDjango + Backbone.js

BackboneModels

for managing data / syncing with server

!

Router wrapper around History API

DemosThe Old School Application

PJAX & History API

Nesting Views & Modals

Discoverability (HATEOAS)

Animation

Push or Replace

Staying In Sync

The Old School Application

Demo 1

Basic PJAX & History API

PJAXPushState + A JAX

Normal vs PJAX

Browser makes normal request

Server responds with full HTML document

server

Browser

Normal Request

Normal vs PJAX

Browser makes PJAX request and updates

location bar

Server responds with partial HTML

document

server

Browser

PJAX Request

jQuery-PJAX

https://github.com/defunkt/jquery-pjax

PJAX Container

Identify where the partial HTML will be inserted

<div class="container" id="pjax-container">

Go to <a href=“/page/2" data-pjax>next page</a>.

</div>

$(document).pjax(a[data-pjax]', '#pjax-container')

PJAX Requests

Inform the server that you don’t want the full page, just the partial

Could use a custom request header

If the browser doesn’t support the History API fallback to normal request

PJAX Requests

If browser supports History API then intercept links and make PJAX request

<a href=“/my-page/“ data-pjax>link</a>

and

XHR.setRequestHeader(‘X-PJAX’)

PJAX - Serverdef myView(request):

if request.headers[‘X-PJAX’]:

return renderPartial()

else:

return renderLayout()

PJAX Benefits

Fewer requests

Fast response

Reduced load on server

Bookmarkable URL

Degrades nicely

History APISession History and Navigation API

Session History Browser Support

Traditionalhttp://website.com/index.html

Traditionalhttp://website.com/about.html

about

Unique resource has unique URL

Traditional + A JAXhttp://website.com/index.html

Traditional + A JAXhttp://website.com/index.html

about

Unique resource has shared URL

PushState + A JAXhttp://website.com/index.html

PushState + A JAXhttp://website.com/about.html

about

Unique resource has unique URL again

PushState

var stateObj, title, url;

stateObj = {name: "fred"}

url = "/fred";

history.pushState(stateObj, title, url);

PushState

www.bbc.co.uk

www.bbc.co.uk/fred {}

www.bbc.co.uk/news/

Update the UI e.g. via ajax

PopState Event

window.onpopstate = function(e) {

console.log(e.state);

}

PopState Event

the popState event is fired when you go back and forward in the browser history

the state object assigned to the url is returned on a property of the event called state

this allows you to reconstruct the page without a full reload

PopState

www.bbc.co.uk

www.bbc.co.uk/fred

www.bbc.co.uk/news/

{}

DemoMaster - Detail with PJAX

Visual Cues

Visual Cues

Browsers have traditionally given visual cues

More power for developers (A JAX, History API)

Remember to keep the user in the loop

Slow down connection or put setTimeout in jquery send

https://github.com/defunkt/jquery-pjax

$(document).on('pjax:send', function() {

$('#loading').show()

})

$(document).on('pjax:complete', function() {

$('#loading').hide()

})

PJAXIn the wild

PJAX - Who’s using it?

https://blog.twitter.com/2012/improving-performance-on-twittercom

http://www.youtube.com/watch?v=hrZl_EQUbRQ

http://bit.ly/1hG3GTi

Backbone.js

Nesting Views & Modals

Demo 3

Event Delegation & Element Lifetime

Element Lifetime

Short lifetime (view)

Short lifetime (view)

Long lifetime (container)

Event Delegation

Delegate events to elements with a long lifetime

Events fired on newly inserted HTML bubble up to container (delegate)

Fewer event handlers

Event Delegation (jQuery)

$(container).on(‘click’, ‘a[data-pjax]’, function(){

do_something();

});

HATEOASHypermedia As The Engine Of Application State

Sport Link

What if there were no linksAnd instead, the BBC published a document detailing

URL’s of all their pages

+BBC WEBSITE

URLS !

VERSION 1.0

BBC WEBSITE URLS

!VERSION 2.0

BBC WEBSITE URLS

!VERSION 3.0

Don’t cook URLs on the client, instead use the URLS

provided by the serverDecouples the client from the server

Discoverability (HATEOAS)

Demo 4

Animation & the Back Button

AnimationFeedback for the user is vital

Helps to suggest the behaviour of the back button

Helps to suggest available touch events

Native mobile/desktops rely on animation to help the user feel in control of the application

UX is predictable

Animation

Demo 5

Animation

Spotify Web Player

Twitter App

Back Button

http://www.xkcd.com/1309/

http://www.reddit.com/r/programming/comments/1uou3g/please_respect_the_back_button/

Push or Replace

Demo 6

Push or Replace

history.pushState vs history.replaceState

Is this a new state or are we just altering the existing state?

How are we presenting states? What will the typical user want to do?

User Testing

ReplaceState

some potential use cases

Modal dialogues - users probably don't expect the back button to undo the modal

Setting up the first page a user visits so we can recreate state when they hit back

Staying In Sync With The Server

Staying In Sync With The Server

PJAX makes updating a part of the page easy

What about other representations of the same entity which already exist on the page?

Allow parts of the page to become stale or occasionally refresh the page (jquery-idletimer)

Assign URL’s to components on the page

Assign URLs to components

/image/58/panel/

/image/57/panel/

/image/56/panel/

Staying In Sync With The Server

Demo 7

Staying In Sync With The Server

Pros: Master and detail view stay in sync

Cons: making multiple requests for content

Staying In Sync With The Server

How can we make a single request?

Server-Sent Events

Send HTML in JSON

Generic approach to updating content on the client with JSON & HTML

Staying In Sync With The Server

{

“content”: [

“div.thing”: “<p>content</p>”,

“div.related”: “<p>related content</p>”

]

}

Staying In Sync With The Server

Sending HTML/JSON could work but lots of benefits of using SSE:

Uses Traditional HTTP

Automatic reconnection

Send any type of event

SummaryPJAX - PushState+A JAX, URLs are important in modern JS heavy

apps

HATEOAS - decoupling client from server

Element Lifetime & Event Delegation - binding to long lived element

Push or Replace - what should the back button do?

Animation - important for user feedback

Staying in Sync - giving components URLs

ThanksQuestions

James Da Costa

@jamesdacosta james@bright-interactive.com

jamesdacosta.com

Recommended