Upload
james-da-costa
View
2.276
Download
0
Embed Size (px)
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 [email protected]
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
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
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/
Epistemic Action
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