Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Architecting single-page front-end apps

42,235 views

Published on

Published in: Technology
  • Be the first to comment

Architecting single-page front-end apps

  1. 1. Architecting single-page Web appsZohar Arad. June 2011
  2. 2. Quick intro Front-end architect and developer Been building websites since 2004 3 years as Metacafe’s leading front-end developer MooTools, Rails, Ruby, Mac, Linux enthusiast Front-end is my main game. I also know the back-end quite well
  3. 3. Single-page Web apps.
  4. 4. We’re going to cover Basic concepts Client-server relationship Routing Views and content rendering Global event handling
  5. 5. We’re going to cover Dependency management Code initialization and execution Form handling Final thoughts
  6. 6. Basic concepts One view, many partials Rely on async requests for fetching and sending data No page refresh - Update content in place Desktop application user-interaction model RESTful client-server communication
  7. 7. Problems and challenges When are various components included and initialized? How do we define generic interaction for separate components? How do we send, receive and render data asynchronously? How do we avoid re-initialization of existing components? What happens when things break?
  8. 8. A word of caution Single-page applications should work without Javascript. If you only rely on Javascript without gracefully degrading to non-javascript functionality you’re doing it wrong! This is true most of the times...
  9. 9. Client-server relationship
  10. 10. Client-server relationships Most single-page apps require a server to handle data and business logic (CouchApps excluded) We start planning and building the server-side We define routes, controllers, actions and views as we would for ordinary web apps
  11. 11. Why??No server = no applicationWe need solid conventions for both sides of the applicationThe client is a consumer, not a service provider
  12. 12. Give it a RESTPlanning routes
  13. 13. RESTYour client and server should agree how to communicateREST helps you define which resource represents whichaction or stateYour URLs should be defined on the server andimplemented by the clientDo not reinvent the wheel (URL generators)
  14. 14. REST and HTTPRemember HTTP verbs and conventionsGET is used to read dataPOST / PUT are used to write / update dataDELETE is used to remove data
  15. 15. Data renderingViews and templates. Sans-rain-deer
  16. 16. Rendering HTMLView / partial paradigm Full view is rendered in normal request Partial view is rendered in XHRDRY - write your HTML only once
  17. 17. Rendering HTMLServer side should generate HTML whenever possible Why should the client generate HTML? We need to manage HTML generation in one place Localization is easier on the server-side Server-side performance is absolute and known
  18. 18. What about JSONJSON.... We love you man!
  19. 19. Rendering HTMLYou need to ask yourself why should you use JSON insteadof HTML to generate views.You need generic support on both server and clientYou need to justify the overhead of HTML generation
  20. 20. Rendering HTMLSeriously - If you can handle HTML on the server, do it.Keep is simple and don’t repeat yourself!
  21. 21. But I love JSONSeriously, just look at the guy!
  22. 22. Data passing with JSON We’d use JSON to pass data to the client when We’re not rendering HTML (e.g. forms, APIs) There’s no other option Bandwidth is expensive Business logic is in the browser
  23. 23. Global eventsOne event to rule them all and in the browser bind them
  24. 24. Global Events We have bits of HTML loaded asynchronously We already initialized event handles on replaced HTML We want to avoid re-binding event handles with each DOM update
  25. 25. Global Events function globalClickHandler(e){ var tgt = $(e.target); do { tag = tgt.get(tag); if (tag === a) { /** do something with link **/} tgt = tgt.getParent(); } while (tag !== body); } document.addEvent(‘click’,globalClickHandler);
  26. 26. Global Events We can use the same principle to any other event we want to handle globally We can handle form submission for example Keyboard events Form widgets events
  27. 27. Global Events Issues to remember: We have some redundant DOM traversal We should strive to unbind events on unload Too much is no good (don’t over do it)
  28. 28. Dependency Management
  29. 29. Dependency ManagementThree approaches Brute and Hungry Requires Script tags
  30. 30. Dependency ManagementBrute and Hungry We load everything when page loads We need to ensure things are packed nicely Jammit or Sprockets Large file limitations (caching, parsing, network) Change in one file forces full cache purge
  31. 31. Dependency ManagementRequires Use a JS dependency library (require.js, head.js) script-ready support load only when needed requires a bit more logic to ensure things run after requires
  32. 32. Dependency ManagementScript tags Fetch JS script tags with HTML Add to DOM once Binds view and JS (good or bad?) Readiness and requiring management needed
  33. 33. Dependency ManagementBrute and Hungry - Small JS apps / non-mobile appsRequires / Script tags - Larger / more complex appsRequires are probably the best solution out there Flexible Functional and Intuitive Penalties are “less” severe
  34. 34. Initialization and ExecutionExecuting things without breaking your neck
  35. 35. Initialization and execution Our code needs to run at certain points or respond to certain user interactions. How do we know when to initialize and execute the relevant bits of code?
  36. 36. Initialization and execution We initialize our application’s entry point module on DOM ready If we’re using requires, we can initialize required modules when they’re required
  37. 37. Initialization and execution We have a global handler for async requests We can execute response callbacks based on request URL We can return a bit of Javascript with each response that will be executed when the content is rendered
  38. 38. Initialization and execution Finally, we can use an Initializer pattern to call various modules based on some convention: We need module construction and destruction We know what action was performed on the server (e.g. controller name and action name)
  39. 39. Initialization and execution var Initializer = { last_action:null, init:function(action){ if(this.last_action && typeof(this.Destructors[this.last_action]) === ‘function’){ this.Destructors[this.last_action](); } if(typeof(this.Constructors[action]) === ‘function’){ this.Constructors[action](); } this.last_action = action; } };
  40. 40. Initialization and execution Initializer.Constructors = {}; Initializer.Destructors = {}; /** Somewhere in a module **/ Initializer.Constructors.Gallery = function(){....} Initializer.Destructors.Gallery = function(){....}
  41. 41. Initialization and execution /** Our global request handler **/ var Request = { get:function(url){ var xhr = new Request({ url:url, onSuccess:function(response){ // render response here Initializer.init(url.split(‘/’)[1]); } }); xhr.get(); } }
  42. 42. Handling forms Handle GET and POST requests separately Form validation is the server’s job!!! The client should assist the user to fill correct values Use server-side validation errors in the client Rely on HTTP error statuses to handle success / failure
  43. 43. Handling forms You can have a global form handler, similar to your global request handler Async responses should be: JSON when we check success / failure HTML when we render something after submission Define a coherent API to pass data from server to client on form submission
  44. 44. Final thoughts We didn’t talk about Performance, MVC, Couch Apps, templates Do what’s right based on your requirements Learn a goddamn server-side framework
  45. 45. Final thoughts Design for simplicity Don’t repeat yourself and don’t reinvent the wheel Start small and grow larger (modules anyone?) Define developer-friendly conventions and follow them

×