Upgrade to Pro — share decks privately, control downloads, hide ads and more …

templates and the single-page app of the future (updated)

Garann Means
November 13, 2012

templates and the single-page app of the future (updated)

JavaScript templates are hardly a new idea. They've been around for years, and by now we have several popular forerunners. It's not always clear, however, what kind of templates we should use, and how to use them most efficiently. And there are less obvious uses that often only become apparent in the abstract or in hindsight.
We'll look at the metrics you should evaluate when choosing a template engine and different ways of actually implementing them. We'll go beyond the client and touch on some of the things that become possible with templates and Node.js. Hopefully, we'll come away knowing the right answers to all our template questions, and some new places to ask them.

Garann Means

November 13, 2012
Tweet

More Decks by Garann Means

Other Decks in Technology

Transcript

  1. Templates
    and the
    single-page app
    of the future!
    @garannm - http://garann.com
    1

    View Slide

  2. a sht histy
    2

    View Slide

  3. timeline
    ☞static content
    ☞“classic” asp, php, et al
    ☞decoupled server-side templates
    ☞ajax & dom manipulation
    ☞single-page apps and client-side templates
    3

    View Slide

  4. ye old templating
    4

    View Slide

  5. remember this:


    <%
    sub vbproc(num1,num2)
    response.write(num1*num2)
    end sub
    %>


    Result: <%call vbproc(3,4)%>


    5

    View Slide

  6. templates circa ajax
    server client
    server
    page
    ajax
    template
    template
    template
    template
    template
    template
    template
    template
    template
    ajax
    6

    View Slide

  7. templates post-ajax
    ☞sending JSON, not html
    ☞rendering via dom manipulation
    ☞decoupled server-side
    ☞fallback for non-js clients
    ☞tied to request-response
    7

    View Slide

  8. templates post-ajax
    8

    View Slide

  9. yeah, but..
    ☞too much dom manipulation makes a mess
    ☞it was really slow
    ☞lots of duplicate code
    ☞rendering coupled to user interaction
    9

    View Slide

  10. templates post-post-ajax
    10

    View Slide

  11. the contenders
    11

    View Slide

  12. verbose logic
    ☞can use pure data
    ☞mimics classic server-side templates
    ☞less parsing required
    ☞initial implementations pretty ugly
    ☞modern implementations among the fastest
    12

    View Slide

  13. logic-less
    ☞needs presentation-ready data
    ☞decouples presentation and code
    ☞easier for designers?
    ☞template is a dumb renderer
    ☞which is safer
    13

    View Slide

  14. remember this?


    <%
    sub vbproc(num1,num2)
    response.write(num1*num2)
    end sub
    %>


    Result: <%call vbproc(3,4)%>


    14

    View Slide

  15. what everyone’s so upset
    about




    Result: <%= num1*num2 %>


    15

    View Slide

  16. string concatenation
    ☞how it’s (mostly) done
    ☞fast
    ☞flexible
    ☞output not really reusable
    ☞have to search for individual elements
    16

    View Slide

  17. dom elements
    ☞not common
    ☞engines using html attributes may not return a dom
    ☞allows “data view” type control
    ☞references to elements and their relationships
    17

    View Slide

  18. non-template-tag format
    ☞most template engines don’t care about format
    ☞can be used for things besides html
    ☞some rely on html
    ☞some assume haml (or similar)
    18

    View Slide

  19. a little help?
    19

    View Slide

  20. typical sitch
    ☞mustaches {{...}}
    ☞some logic (conditions, loops, partials)
    ☞pre-compilation for reuse
    ☞server- or client-side
    ☞string concatenation for speed
    ☞format agnostic
    20

    View Slide

  21. rendering vs.
    manipulation
    21

    View Slide

  22. simple template
    Welcome back, {{username}}!
    Your friends:

    {{#friends}}
    {{name}}
    {{#if online}}
    online
    {{/if}}
    {{/friends}}

    22

    View Slide

  23. data
    var userObj = {
    username: “tmplM4st3r”,
    friends: [
    { name: “1337tmpls”, online: true },
    { name: “hbars4lyfe”, online: true },
    { name: “belieber42”, online: false }
    ]
    };
    23

    View Slide

  24. rendered
    Welcome back, tmplM4st3r!
    Your friends:

    1337tmpls
    online
    hbars4lyfe
    online
    belieber42

    24

    View Slide

  25. loading
    ☞most template engines will accept any string
    ☞script tag with non-rendered type
    ☞external file loaded via ajax or a loader
    ☞string concatenated into js during build
    ☞more fragile
    25

    View Slide

  26. loading & compiling
    var $container, myTmpl, userObj;
    $.get( “templates/user.tmpl”, function( tmpl ) {
    myTmpl = Handlebars.compile( tmpl );
    $container.html( myTmpl( userObj ) );
    }, “text” );
    26

    View Slide

  27. loading & compiling
    function renderUser( cb ) {
    if ( myTmpl ) {
    cb();
    return;
    }
    $.get( “templates/user.tmpl”, function( tmpl ) {
    myTmpl = Handlebars.compile( tmpl );
    cb();
    }, “text” );
    }
    renderUser( function() {
    $container.html( myTmpl( userObj ) );
    });
    27

    View Slide

  28. uh oh..
    socket.on( “friendOffline”, function( friend ) {
    var friends = userObj.friends;
    $.each( friends, function( i, f ) {
    if ( friend.name === f.name ) {
    f.online = friend.online;
    }
    });
    renderUser( function() {
    $container.html( myTmpl( userObj ) );
    });
    });
    28

    View Slide

  29. alternatively
    socket.on( “friendOffline”, function( friend ) {
    $( “a[data-name=” + friend.name + “]” )
    .next( “span” )
    .remove();
    });
    29

    View Slide

  30. But what if..
    Welcome back, {{username}}!
    Your friends:

    {{#friends}}

    {{> friend }}

    {{/friends}}

    30

    View Slide

  31. defining a partial
    Handlebars.registerPartial( ‘friend’,
    ‘{{name}}’ +
    ‘{{#if online}}’ +
    ‘online’ +
    ‘{{/if}}’ );
    var friendTmpl = “{{> friend }}”;
    31

    View Slide

  32. and so!
    socket.on( “friendOffline”, function( friend ) {
    $( “div[data-name=” + friend.name + “]” )
    .html( friendTmpl( friend ) );
    });
    32

    View Slide

  33. composition choices
    ☞how much dom manipulation is needed?
    ☞how likely is re-rendering?
    ☞how difficult is it to find the child element?
    33

    View Slide

  34. client-side
    architectures
    34

    View Slide

  35. mvc
    ☞view and template often synonymous
    ☞in practice, need a view-model
    ☞controller determines when to render
    ☞need non-mvc concepts
    ☞rendering container
    ☞event handlers
    35

    View Slide

  36. a “view”
    ☞the template
    ☞its container/rendering target
    ☞view-model/transformation logic
    ☞event handling?
    ☞actually a bunch of stuff
    36

    View Slide

  37. abstracted rendering
    ☞a complete view should only need to be told when to
    render
    ☞everything may not be a complete view
    ☞e.g. partials
    ☞everything may not map perfectly to a model
    37

    View Slide

  38. templates filling in gaps
    ☞non-application parts of the page
    ☞pieces of proper models
    ☞non-data input structures (e.g. confirmation)
    ☞sub-views within proper views
    38

    View Slide

  39. templates without mvc
    ☞map to states, not data
    ☞generic renderer or tight coupling
    ☞triggered by event, object.observe()
    ☞may need more partials
    ☞more data potentially hard-coded
    39

    View Slide

  40. with subscribers
    function Renderer() {
    this.render = function( data ) {
    data.container.html(
    Handlebars.compile( data.tmpl )( data.obj ) );
    };
    return this;
    });
    Renderer.subscribe( ‘formInit’, this.render );
    Renderer.subscribe( ‘formInvalid’, this.render );
    Renderer.subscribe( ‘formSubmitted’, this.render );
    40

    View Slide

  41. with observers
    UserData.prototype = {
    get value() {
    return this._value;
    };
    set value( val ) {
    this._value = val;
    this._container.html(
    Handlebars.compile( this._tmpl )( val ) );
    };
    };
    41

    View Slide

  42. in any architecture
    ☞decouple markup from code
    ☞reduce need for dom manipulation
    ☞move rendering to an abstraction
    42

    View Slide

  43. node.js
    43

    View Slide

  44. not dissimilar from client
    44

    View Slide

  45. server-side uses
    ☞initial load
    ☞full-page rendering
    ☞server-side compilation (hogan.js)
    ☞rendered html snippets
    45

    View Slide

  46. dumb views
    ☞server-side mvc is different
    ☞more models
    ☞more controllers
    ☞less views
    ☞view is single-use
    ☞user interaction not relevant
    46

    View Slide

  47. presentation logic
    ☞still needed for rendering
    ☞does this belong on the server?
    ☞is it necessary?
    ☞can it be shared?
    ☞isomorphic view-models and validation
    47

    View Slide

  48. type of template matters
    ☞may be better for haml et al
    ☞server-side dom pointless
    ☞except for scraping/crawling
    ☞performance matters less
    ☞but are you only using templates on the server?
    48

    View Slide

  49. full-stack templates
    49

    View Slide

  50. the good stuff
    ☞use the template for initial load
    ☞reuse it to render new data
    ☞same template for:
    ☞server-side controller (url)
    ☞client-side controller (location.hash)
    50

    View Slide

  51. shared access
    ☞easiest to use same loader
    ☞e.g. Require with text plugin
    ☞no need to create two versions
    51

    View Slide

  52. managing partials
    ☞can be difficult depending on template engine
    ☞argues for larger templates
    ☞namespaces work differently
    ☞scope unreliable
    52

    View Slide

  53. solutions appearing
    53

    View Slide

  54. full-stack frameworks
    ☞reuse the framework, reuse the templates
    ☞not there yet
    ☞but people are working on it
    ☞express, geddy use templates available on client
    ☞meteor, derby use their own
    54

    View Slide

  55. where that leaves us
    ☞client-side templates: check
    ☞complex client-side apps: check
    ☞reuse on the server: check
    ☞one unified do-it-all solution: ..to be continued!
    55

    View Slide

  56. thanks!
    @garannm - http://garann.com
    56

    View Slide

  57. credits
    ☞ http://www.flickr.com/photos/ndayla/5531142284/
    ☞ http://www.flickr.com/photos/ndayla/5559712259
    ☞ http://www.flickr.com/photos/[email protected]/2692285853/
    ☞ http://www.flickr.com/photos/reebob/3294745178/
    ☞ http://www.flickr.com/photos/jeckcrow/4407422983/
    ☞ http://www.flickr.com/photos/legends2k/5410967229/
    57

    View Slide