Single page apps with Symfony and chaplin.js

Single page apps with Symfony and chaplin.js

Talk about making Symfony and chaplin.js/backbone.js play nicely together.

F7812e1b64fe2bbcee7a8637e1808ec2?s=128

Robert Gründler

January 16, 2013
Tweet

Transcript

  1. SINGLE PAGE APPLICATIONS built with Symfony and chaplin.js Monday, January

    14, 13
  2. WHO AM I • Freelance software developer in Vienna •

    Working with Symfony since 2008 • github.com/pulse00 • twitter.com/pulse00 • blog.dubture.com Monday, January 14, 13
  3. GOALS Monday, January 14, 13

  4. FULLY FUNCTIONAL SINGLE PAGE APPLICATION • REST API secured with

    oauth2 • 2-leg authenticated chaplin.js webclient Monday, January 14, 13
  5. WHAT SHOULD YOU KNOW ? • Symfony basics • Doctrine

    basics • Javascript / jquery basics Monday, January 14, 13
  6. WHY BUILDING SUCH A THING IN THE FIRST PLACE? Monday,

    January 14, 13
  7. PROS • Reduced payload for your HTTP requests • Don’t

    reload your page markup on every request • Perceived UI performance improvement for endusers • Maintain a single REST API for multiple clients(web/mobile/etc) • Allows continuous media streams between page reloads • Ideal solution for audio content Monday, January 14, 13
  8. CONS • SEO issues for public facing websites • Client-Side

    frameworks are not very mature • New debugging challenges • Large development overhead when supporting old browsers Monday, January 14, 13
  9. BOOKSTORE APPLICATION • Provide a CRUD interface for books •

    Interface for browsing books and authors • Adding book reviews Monday, January 14, 13
  10. SETTING UP THE BACKEND Monday, January 14, 13

  11. 1. ORM ENTITIES Monday, January 14, 13

  12. Monday, January 14, 13

  13. Monday, January 14, 13

  14. 2. REST CONTROLLERS Monday, January 14, 13

  15. to the rescue! github.com/FriendsOfSymfony/FOSRestBundle Monday, January 14, 13

  16. CONFIGURATION Enable the view response listener to automatically serialize return

    values from controllers Disable framework default view annotations Monday, January 14, 13
  17. ROUTING app/config/routing.yml AcmeSPAApiBundle/Resources/config/routing.yml Enable automatic REST route generation Monday, January

    14, 13
  18. Makes FOSRestBundle create routes based on the controller name. Makes

    FOS view-response- listener automatically serialize the return value of the controller. Monday, January 14, 13
  19. GET http://bookstore.local/api/books /api/books endpoint serializes all book attributes to json

    by default. Monday, January 14, 13
  20. GET http://bookstore.local/api/books.xml same resource serialized to XML Monday, January 14,

    13
  21. CONTROLLING ENTITY SERIALIZATION github.com/schmittjoh/JMSSerializerBundle Monday, January 14, 13

  22. SERIALIZATION GROUPS GET /books serializes using “bookList” group GET /books/{id}

    serializes using “bookDetail” group Monday, January 14, 13
  23. Exclude all attributes from serialization by default Expose attributes only

    when specific serialization groups are active Monday, January 14, 13
  24. GET /api/books “books” relation is not serialized anymore Monday, January

    14, 13
  25. POSTING NEW BOOKS Monday, January 14, 13

  26. BASE API FORMTYPE Disable CSRF protection as our secure API

    will be accessible only using oauth2 authentication getName() returns null to make the REST PUT format of backbone.js compatible when binding the form. Monday, January 14, 13
  27. Serializes validation errors to json/xml Request method restricted to POST

    by FOSRestBundle Monday, January 14, 13
  28. TESTING THE ENDPOINT Monday, January 14, 13

  29. USING CURL Monday, January 14, 13

  30. UPDATING BOOKS Monday, January 14, 13

  31. Re-Use the processForm() method Monday, January 14, 13

  32. DELETING BOOKS Monday, January 14, 13

  33. FOSRestBundle sets status code to 204 automatically Monday, January 14,

    13
  34. GENERATED REST ENDPOINTS Monday, January 14, 13

  35. SECURING CRUD ENDPOINTS with oauth2 using FOSOauthServerBundle Monday, January 14,

    13
  36. config.yml See FOSOauthServerBundle documentation for setting up orm entities. github.com/FriendsOfSymfony/FOSOAuthServerBundle

    Monday, January 14, 13
  37. API endpoints secured through stateless oauth2 Regular website secured through

    cookie based form login oauth2 token retrieval oauth2 authorization endpoint for 3-legged auth security.yml Monday, January 14, 13
  38. Monday, January 14, 13

  39. RECAP Monday, January 14, 13

  40. RECAP so far we have Monday, January 14, 13

  41. RECAP so far we have 1. REST API endpoints for

    the book entities Monday, January 14, 13
  42. RECAP so far we have 1. REST API endpoints for

    the book entities 2. Oauth2 secured CRUD controllers Monday, January 14, 13
  43. RECAP so far we have 1. REST API endpoints for

    the book entities 2. Oauth2 secured CRUD controllers 3. A fully tested API Monday, January 14, 13
  44. CHAPLIN.JS • CoffeeScript HTML5 application framework • Based on backbone.js

    • Cross-module communication • Controllers for managing individual UI views • Strict memory management and object disposal • Nested views • ... github.com/chaplinjs/chaplin Monday, January 14, 13
  45. BRUNCH • HTML5 application assembler and build tool • Compiles

    your chaplin.js application into javascript • Compiles Stylus/Sass/Less/YouNameIt into CSS • tons of other useful features github.com/brunch/brunch Monday, January 14, 13
  46. CREATING THE CHAPLIN APP • Install brunch (see http://brunch.io for

    details) • Run “brunch new client” in your Symfony app root Monday, January 14, 13
  47. chaplin client application brunch configuration chaplin application tests javascript dependencies

    compiled javascripts and stylesheets generated during brunch compilation process Generated application structure Monday, January 14, 13
  48. Customize config.coffee Tell brunch to compile js/css files into the

    Symfony document root Monday, January 14, 13
  49. main application twig template Acme/SPA/ChaplinBundle/Resources/views/layout.html.twig application css compiled by brunch

    application javascript compiled by brunch initialize the client app Monday, January 14, 13
  50. BACKBONE/CHAPLIN ROUTING client/app/routes.coffee will match http://bookstore.local will match http://bookstore.local/books will

    NOT match: •http://bookstore.local/app_dev.php •http://bookstore.local/app_dev.php/books Monday, January 14, 13
  51. to the rescue! github.com/FriendsOfSymfony/FOSJsRoutingBundle Monday, January 14, 13

  52. The controller for the frontend only has a single action

    rendering the application layout. Use the expose option to make the chaplin router aware of the Symfony routes. All routes use the same controller action. Monday, January 14, 13
  53. Acme/SPA/ChaplinBundle/Resources/views/layout.html.twig Dump exposed routes to javascript Monday, January 14, 13

  54. Use regular Symfony route names in the backbone router Matches

    URLs in the correct app environment (app_dev.php/books for example) (see client/app/symfony_router.coffee for the SymfonyRouter coffeescript implementation in the github demo app) Monday, January 14, 13
  55. IMPLEMENTING THE BOOKS LIST Monday, January 14, 13

  56. initialize a books list plus the corresponding view and fetch

    the data when a book_list route matches The Books collection retrieves it’s backend URL from the SymfonyRouter Model and Controller app/controllers/book.coffee app/models/books.coffee Monday, January 14, 13
  57. The collection view renders the book collection app/views/book/list.coffee app/views/book/list_item.coffee app/views/templates/book/list.hbs

    app/views/templates/book/list_item.hbs The collection view will pass the book model for each collection item to the corresponding ItemView Monday, January 14, 13
  58. Generated markup Monday, January 14, 13

  59. Authentication Monday, January 14, 13

  60. Implement an AuthenticationSuccessHandlerInterface Retrieve an oauth2 AccessToken for the chaplin

    client Monday, January 14, 13
  61. Render the login form into a modal view POST the

    login form via ajax Publish a “login success” event client/app/views/auth/login-view.coffee Monday, January 14, 13
  62. Handling Search Engines Monday, January 14, 13

  63. • Follow Googles escaped_fragment specification [1] • Use a headless

    browser to render your page for crawlers [2] • Pre-render <head> tags to make facebook et al. happy STRATEGIES [1] developers.google.com/webmasters/ajax-crawling/docs/specification [2] github.com/apiengine/seoserver Monday, January 14, 13
  64. HEADLESS BROWSERS http://bookstore.com/books http://bookstore.com/books?escaped_fragment= RewriteCond %{QUERY_STRING} ^_escaped_fragment_=(.*)$ RewriteRule (.*) http://address-of-seoserver:3000/%1?

    [P] Apache rewrite fun Monday, January 14, 13
  65. PRE-RENDER <HEAD> METAS github.com/sonata-project/SonataSeoBundle Monday, January 14, 13

  66. New initial page header provides crawler meta information Monday, January

    14, 13
  67. Great and everything - but now we have two database

    trips for every initial pageload instead of one... Monday, January 14, 13
  68. BookController.php layout.html.twig Monday, January 14, 13

  69. book-controller.coffee Only load the model from the server in case

    there was no initial payload embedded Monday, January 14, 13
  70. Demo application available at github.com/pulse00/symfony-chaplin-demo Thanks. Monday, January 14, 13