The Curious Case of
                         Dust
                          @vybs




Wednesday, July 11, 12
Curious about?

                    • Is logic-less working for us?
                    • Are we DRY?
                    • How much on the client?
                    • Really? is it more than just a blog post?
                         Show me the proof



Wednesday, July 11, 12
Let’ start



Wednesday, July 11, 12
How to Dust?



Wednesday, July 11, 12
•   “Dust is a JavaScript templating
                             engine designed to provide a clean
                             separation between presentation and
                             logic without sacrificing ease of use”

                         • “A pure JavaScript library, Dust runs
                             in both browser-side and server-side
                             environments.”




Wednesday, July 11, 12
Ok whatever!



Wednesday, July 11, 12
Really, tell me how
                         it works?


Wednesday, July 11, 12
1. Dust for markup                                2. JSON for data
                 _t = “Hello {name}!          json = {
                  You have {count} new          "name": ”James",
                 messages from                  "count": 2,
                    {#people}                   “people” : [{ “name” : “Jim”,
                        {name},                               “distance” : “2”
                      {/people}                             },{ “name”: ”Eran”
                   ”;                                          “distance” : “1”}
                                                            ]
                                                     }


                         !dust.render(_t, json, function(error, data) {!
                             $(“mydiv”).html(data);!
                          }!                        3. JAVASCRIPT for render

                               Hello James! You have 2 new
                                  messages from Jim, Eran!    4. HTML


Wednesday, July 11, 12
Tell me more!



Wednesday, July 11, 12
1. Dust Keys
                            references in JSON
     Hello {name}!
     You have {count} messages
     from
          {#people}
               {name},
          {/people}
                          2. Dust Sections
                         create a block for enumeration,
                                transformations




Wednesday, July 11, 12
Wait, is that it?



Wednesday, July 11, 12
Curious case of logic-less dust
Wednesday, July 11, 12
Is logic-less working?



Wednesday, July 11, 12
Let’s consider a LI
                              use case


Wednesday, July 11, 12
Use case
        Profile Connections                 Search Results




                         People You May Know
          Member Photo

                                                   ICON/BADGE




Wednesday, July 11, 12
It is just a badge!




Wednesday, July 11, 12
BADGE localized

               ENGLISH


                TURKEY


     PORTUGUESE


           JAPANESE

Wednesday, July 11, 12
How do we solve this simple use
                        case?

Wednesday, July 11, 12
Dust helpers

                    • Macro tags to the rescue, can be written
                         once, hence support DRY
                    • Takes params and executes in the context
                         they are declared
                    • uses the @ notation

Wednesday, July 11, 12
“icon” : {
                                                              “distance” : “1”,
                                                              “first” : “Bill”,
                                                              “last” : “Scott”
                         {#icon name="Bill Scott"}            }
                          {@if cond="{distance} == 0"}
                            <span class="network-degree you">
                             {@i18n key="YOU" text="YOU"/}
                            </span>
                           {:else}
                            {@if cond="{distance} == 1"}
                            <span class="network-degree one">
                           {@i18n key="FIRST" text="{name} is your connection"/}
                             </span>
                             {:else}
                                  ...
                                {/if}
                             {/if}
                          {/if}
                                                         logic = @if
                         {/icon}                 formatted name = @fmt
                                                  localized text = @i18n


Wednesday, July 11, 12
Helper code




                https://raw.github.com/linkedin/dustjs/master/lib/dust-
                                      helpers.js

Wednesday, July 11, 12
Curious about?

                    • Is logic-less working for us?
                    • Are we DRY?
                    • How much on the client?
                    • Really? is it more than just a blog post?
                         show me the proof



Wednesday, July 11, 12
Lets solve the badge
                     differently!


Wednesday, July 11, 12
Dust Partials

                    • Nested templates, have access to the
                         scope of the parent template
                    • Takes params and uses the “>” notation
                    • Partial names can be dynamic


Wednesday, July 11, 12
{
                                          "name": ”James",
                                          "count": 2,
                                          “people” : [{ “name” : “Jim”,

      badge.tl                                          “distance” : “2”
                                                      },{ “name”: ”Eran”
                                                         “distance” : “1”}
            {#people}
                                                      ]
            <li>
             {>”tl/shared/badge_{distance}”/} }
            </li>
            {/people}

       badge_1.tl                                  logic = dynamic
           {@i18n text=“first degree”/}
                                                        partials
       badge_2.tl
             {@i18n text=“second degree”/}
                                                   localized text =
                                                        @i18n


Wednesday, July 11, 12
“Partial” as a Helper
                            @partial, @jsControl




Wednesday, July 11, 12
{#people}
                          Partial as a helper
             {@partial altText=_memberFullName pictureId=primaryPictureID}
                  {>"tl/shared/member_photo"/}
             {/partial}                               pymk.tl includes member_photo.tl
          {/people}
        {!
        Renders Member's profile photo if pictureId is passed otherwise renders ghost image
           @partial member_photo
           @param pictureId {string} Id of photo
           @param size (Integer) Photo Size (default 40) - Photos are always square, so height and width will be same
           @param altText {String} Alt attribute for image
           @param className {String} Optional css class name to be added to the image
        !}


        {@param key="size" defaultVal="40"/}
                                                                                        member_photo.tl
        {?pictureId}
          <img {?className}class="{className}"{/className} {?altText}alt="{altText}"{/altText}
        width="{size}" height="{size}" src='{@pre.link alias="media" args="mediaID:
        {pictureId},mprCommand:shrink_{size}_{size}"/}'>
        {:else}
          <img {?className}class="{className}"{/className} {?altText}alt="{altText}"{/altText}


                                                  • local context, expected
        width="{size}" height="{size}" src='{@pre.img.link path="/img/icon/icon_no_photo_{size}
        x{size}.png"/}'>
        {/pictureId}

                                                       params, docs

Wednesday, July 11, 12
Helper code




                           https://gist.github.com/3083847



Wednesday, July 11, 12
Partial as a helper
    {#Education}
    {#educations}
        {#educations}
          <div id="education-{educationId}" class="editable-item">
            <div id="education-{educationId}-view">
              {>"tl/apps/profile/v2/embed/education_view"/}
            </div>
            {#formData}
            <div id="education-{educationId}-edit" class="edit-form">
              {>"tl/apps/profile/v2/embed/education_edit"/}
            </div>
            {/formData}
          </div>
          {@jsControl name="Sortable.Section"}
                                                           Dust key
            {
              existingDragHandlePath: '.edit-order',
              serverValue: '{educationId}',
              group: 'educations',
              additionalProxyClass:'subsection-drag-proxy'
            }
          {/jsControl}
        {/educations}
    {/educations}
    {/Education}




Wednesday, July 11, 12
QUESTIONS?



Wednesday, July 11, 12
Apps with Dust
                            Browser                            CDN       caching
                                                                         content delivery




     linkedin.com




                            UI /JSON Aggregator
                                                         Static Assets   static content
                                    V8                                   js, css, templates




            apps          Page   Embed     Embed
                                                    Partials


             data layer   JSON    JSON       JSON


Wednesday, July 11, 12
Profile Page




Wednesday, July 11, 12
Anatomy of a LI Page


                    • Page has a Layout
                    • Layout & Page have one or more Embeds


Wednesday, July 11, 12
Profile Page with Embeds
                                                   HEADER




                                                    Ads embed


                                                   WVYP embed


                                                   Activity
                                                    Feed
                                                   embed

Wednesday, July 11, 12
Anatomy of a Embed

                         • Embeds have
                          • Re-usable Dust Helpers
                          • Re-usable Dust Partials
                         • Pages degrade gracefully with embeds
                           that timeout or error



Wednesday, July 11, 12
Page code
        {>"layout"/}
        {<head}
         page specific head {! this is optional !}
         {@pre.scss path=”scss/a,scss/b”/}
        {/head}
        {<body}
         page body
         <script type="fs/embed" fs-uri="{url-to-embed-endpoint_1}">
        </script>
         <script type="fs/embed" fs-uri="{url-to-embed-endpoint_2}">
        </script>
        {/body}
        {<foot}
         page specific foot {! this is optional !}
        {/foot}




Wednesday, July 11, 12
Curious about?

                    • Is logic-less working for us?
                    • Are we DRY?
                    • How much on the client?
                    • Really? is it more than just a blog post?
                         show me the proof



Wednesday, July 11, 12
Curious case of client-rendered dust

Wednesday, July 11, 12
I meant client-rendering
                   and not client-mvc


Wednesday, July 11, 12
How much not on the
                          client?


Wednesday, July 11, 12
! on client
                         • Server side precompiled to JS
                          • Rendering times on client snappy
                                // CDN cached template to js

                                (function(){dust.register(null,body_0);function
                                body_0(chk,ctx){return
                                chk.section(ctx.get("people"),ctx,
                                {"block":body_1},null);}function body_1(chk,ctx)
                                {return chk.write("
                                ").reference(ctx.get("label"),ctx,"h").write("
                                ").reference(ctx.get("FMT_AUTO_NAME"),ctx,"h");}
                                return body_0;})();




Wednesday, July 11, 12
! on client
                         • Server side processed helper tags
                          • auto-generate template dependencies
                                {#people}
                                     {“>tl/shared/badge_{distance}”/}
                                {/people}




Wednesday, July 11, 12
! on client

               • Dust Preprocessed helper tags
                • leverage JVM based i18n, formatting and A/B
                         testing
                     • creates template driven, context based JSON


Wednesday, July 11, 12
Server-side helpers
                   • Similar to client-helpers, takes params, but
                         server processed in the context they are
                         declared
                 {?pictureId}
                   <img {?className}class="{className}"{/className} {?altText}alt="{altText}"{/
                 altText} width="{size}" height="{size}" src='{@pre.link alias="media"
                 args="mediaID:{pictureId},mprCommand:shrink_{size}_{size}"/}'>
                 {:else}
                   <img {?className}class="{className}"{/className} {?altText}alt="{altText}"{/
                 altText} width="{size}" height="{size}" src='{@pre.img.link path="/img/icon/
                 icon_no_photo_{size}x{size}.png"/}'>
                 {/pictureId}




Wednesday, July 11, 12
Wednesday, July 11, 12
! on client

                • No javascript, SEO pages
                • Seamless rendering of dust on the server using
                         V8




Wednesday, July 11, 12
Curious about?

                    • Is logic-less working for us?
                    • Are we DRY?
                    • How much on the client?
                    • Really? is it more than just a blog
                         post? show me the proof



Wednesday, July 11, 12
Is it more than just a
                                blog post?


Wednesday, July 11, 12
We even forked it!



Wednesday, July 11, 12
Is it more than just a
                                blog post?


Wednesday, July 11, 12
We will be open about
                          how we extend and
                            how we use it.



Wednesday, July 11, 12
Seriously, tell me how
                          it is helping us build
                                 features?



Wednesday, July 11, 12
Features
                    • Data-driven product, 60%-65% of features
                         we do are displays
                    • remaining 30-35%
                     • flows, ajaxy interactions
                     • writes/deletes


Wednesday, July 11, 12
Parallel
                           web-development
                         • Logic less templates, language of UX,
                           web-dev, front-end
                         • DRY, medium for quicker turn-around
                         • Mock JSON, language of front-end and
                           back-end



Wednesday, July 11, 12
Ok, tell me which LI
                          pages are in dust!


Wednesday, July 11, 12
•Search App
                         •   https://www.linkedin.com/search-fe/group_search?



                     •Profile

                     •College Alumni Pages
                         •   https://www.linkedin.com/college/alumni



                     •PYMK
                         •   https://www.linkedin.com/people/pymk




Wednesday, July 11, 12
We also are...

                         • Caching templates
                         • Unifying our stack with Javascript
                         • Developing for cross-device
                         • Moving as much as we need, to the client,
                           move as much as we can to JS



Wednesday, July 11, 12
If you watch this presentation backwards,
      it’s should be about a normal web-
               developers’s life!

Wednesday, July 11, 12
we dust!
                         https://github.com/linkedin/dustjs




Wednesday, July 11, 12

Curious case of Dust

  • 1.
    The Curious Caseof Dust @vybs Wednesday, July 11, 12
  • 2.
    Curious about? • Is logic-less working for us? • Are we DRY? • How much on the client? • Really? is it more than just a blog post? Show me the proof Wednesday, July 11, 12
  • 3.
  • 4.
  • 5.
    “Dust is a JavaScript templating engine designed to provide a clean separation between presentation and logic without sacrificing ease of use” • “A pure JavaScript library, Dust runs in both browser-side and server-side environments.” Wednesday, July 11, 12
  • 6.
  • 7.
    Really, tell mehow it works? Wednesday, July 11, 12
  • 8.
    1. Dust formarkup 2. JSON for data _t = “Hello {name}! json = { You have {count} new "name": ”James", messages from "count": 2, {#people} “people” : [{ “name” : “Jim”, {name}, “distance” : “2” {/people} },{ “name”: ”Eran” ”; “distance” : “1”} ] } !dust.render(_t, json, function(error, data) {! $(“mydiv”).html(data);! }! 3. JAVASCRIPT for render Hello James! You have 2 new messages from Jim, Eran! 4. HTML Wednesday, July 11, 12
  • 9.
  • 10.
    1. Dust Keys references in JSON Hello {name}! You have {count} messages from {#people} {name}, {/people} 2. Dust Sections create a block for enumeration, transformations Wednesday, July 11, 12
  • 11.
    Wait, is thatit? Wednesday, July 11, 12
  • 12.
    Curious case oflogic-less dust Wednesday, July 11, 12
  • 13.
  • 14.
    Let’s consider aLI use case Wednesday, July 11, 12
  • 15.
    Use case Profile Connections Search Results People You May Know Member Photo ICON/BADGE Wednesday, July 11, 12
  • 16.
    It is justa badge! Wednesday, July 11, 12
  • 17.
    BADGE localized ENGLISH TURKEY PORTUGUESE JAPANESE Wednesday, July 11, 12
  • 18.
    How do wesolve this simple use case? Wednesday, July 11, 12
  • 19.
    Dust helpers • Macro tags to the rescue, can be written once, hence support DRY • Takes params and executes in the context they are declared • uses the @ notation Wednesday, July 11, 12
  • 20.
    “icon” : { “distance” : “1”, “first” : “Bill”, “last” : “Scott” {#icon name="Bill Scott"} } {@if cond="{distance} == 0"} <span class="network-degree you"> {@i18n key="YOU" text="YOU"/} </span> {:else} {@if cond="{distance} == 1"} <span class="network-degree one"> {@i18n key="FIRST" text="{name} is your connection"/} </span> {:else} ... {/if} {/if} {/if} logic = @if {/icon} formatted name = @fmt localized text = @i18n Wednesday, July 11, 12
  • 21.
    Helper code https://raw.github.com/linkedin/dustjs/master/lib/dust- helpers.js Wednesday, July 11, 12
  • 22.
    Curious about? • Is logic-less working for us? • Are we DRY? • How much on the client? • Really? is it more than just a blog post? show me the proof Wednesday, July 11, 12
  • 23.
    Lets solve thebadge differently! Wednesday, July 11, 12
  • 24.
    Dust Partials • Nested templates, have access to the scope of the parent template • Takes params and uses the “>” notation • Partial names can be dynamic Wednesday, July 11, 12
  • 25.
    { "name": ”James", "count": 2, “people” : [{ “name” : “Jim”, badge.tl “distance” : “2” },{ “name”: ”Eran” “distance” : “1”} {#people} ] <li> {>”tl/shared/badge_{distance}”/} } </li> {/people} badge_1.tl logic = dynamic {@i18n text=“first degree”/} partials badge_2.tl {@i18n text=“second degree”/} localized text = @i18n Wednesday, July 11, 12
  • 26.
    “Partial” as aHelper @partial, @jsControl Wednesday, July 11, 12
  • 27.
    {#people} Partial as a helper {@partial altText=_memberFullName pictureId=primaryPictureID} {>"tl/shared/member_photo"/} {/partial} pymk.tl includes member_photo.tl {/people} {! Renders Member's profile photo if pictureId is passed otherwise renders ghost image @partial member_photo @param pictureId {string} Id of photo @param size (Integer) Photo Size (default 40) - Photos are always square, so height and width will be same @param altText {String} Alt attribute for image @param className {String} Optional css class name to be added to the image !} {@param key="size" defaultVal="40"/} member_photo.tl {?pictureId} <img {?className}class="{className}"{/className} {?altText}alt="{altText}"{/altText} width="{size}" height="{size}" src='{@pre.link alias="media" args="mediaID: {pictureId},mprCommand:shrink_{size}_{size}"/}'> {:else} <img {?className}class="{className}"{/className} {?altText}alt="{altText}"{/altText} • local context, expected width="{size}" height="{size}" src='{@pre.img.link path="/img/icon/icon_no_photo_{size} x{size}.png"/}'> {/pictureId} params, docs Wednesday, July 11, 12
  • 28.
    Helper code https://gist.github.com/3083847 Wednesday, July 11, 12
  • 29.
    Partial as ahelper {#Education} {#educations} {#educations} <div id="education-{educationId}" class="editable-item"> <div id="education-{educationId}-view"> {>"tl/apps/profile/v2/embed/education_view"/} </div> {#formData} <div id="education-{educationId}-edit" class="edit-form"> {>"tl/apps/profile/v2/embed/education_edit"/} </div> {/formData} </div> {@jsControl name="Sortable.Section"} Dust key { existingDragHandlePath: '.edit-order', serverValue: '{educationId}', group: 'educations', additionalProxyClass:'subsection-drag-proxy' } {/jsControl} {/educations} {/educations} {/Education} Wednesday, July 11, 12
  • 30.
  • 31.
    Apps with Dust Browser CDN caching content delivery linkedin.com UI /JSON Aggregator Static Assets static content V8 js, css, templates apps Page Embed Embed Partials data layer JSON JSON JSON Wednesday, July 11, 12
  • 32.
  • 33.
    Anatomy of aLI Page • Page has a Layout • Layout & Page have one or more Embeds Wednesday, July 11, 12
  • 34.
    Profile Page withEmbeds HEADER Ads embed WVYP embed Activity Feed embed Wednesday, July 11, 12
  • 35.
    Anatomy of aEmbed • Embeds have • Re-usable Dust Helpers • Re-usable Dust Partials • Pages degrade gracefully with embeds that timeout or error Wednesday, July 11, 12
  • 36.
    Page code {>"layout"/} {<head} page specific head {! this is optional !} {@pre.scss path=”scss/a,scss/b”/} {/head} {<body} page body <script type="fs/embed" fs-uri="{url-to-embed-endpoint_1}"> </script> <script type="fs/embed" fs-uri="{url-to-embed-endpoint_2}"> </script> {/body} {<foot} page specific foot {! this is optional !} {/foot} Wednesday, July 11, 12
  • 37.
    Curious about? • Is logic-less working for us? • Are we DRY? • How much on the client? • Really? is it more than just a blog post? show me the proof Wednesday, July 11, 12
  • 38.
    Curious case ofclient-rendered dust Wednesday, July 11, 12
  • 39.
    I meant client-rendering and not client-mvc Wednesday, July 11, 12
  • 40.
    How much noton the client? Wednesday, July 11, 12
  • 41.
    ! on client • Server side precompiled to JS • Rendering times on client snappy // CDN cached template to js (function(){dust.register(null,body_0);function body_0(chk,ctx){return chk.section(ctx.get("people"),ctx, {"block":body_1},null);}function body_1(chk,ctx) {return chk.write(" ").reference(ctx.get("label"),ctx,"h").write(" ").reference(ctx.get("FMT_AUTO_NAME"),ctx,"h");} return body_0;})(); Wednesday, July 11, 12
  • 42.
    ! on client • Server side processed helper tags • auto-generate template dependencies {#people} {“>tl/shared/badge_{distance}”/} {/people} Wednesday, July 11, 12
  • 43.
    ! on client • Dust Preprocessed helper tags • leverage JVM based i18n, formatting and A/B testing • creates template driven, context based JSON Wednesday, July 11, 12
  • 44.
    Server-side helpers • Similar to client-helpers, takes params, but server processed in the context they are declared {?pictureId} <img {?className}class="{className}"{/className} {?altText}alt="{altText}"{/ altText} width="{size}" height="{size}" src='{@pre.link alias="media" args="mediaID:{pictureId},mprCommand:shrink_{size}_{size}"/}'> {:else} <img {?className}class="{className}"{/className} {?altText}alt="{altText}"{/ altText} width="{size}" height="{size}" src='{@pre.img.link path="/img/icon/ icon_no_photo_{size}x{size}.png"/}'> {/pictureId} Wednesday, July 11, 12
  • 45.
  • 46.
    ! on client • No javascript, SEO pages • Seamless rendering of dust on the server using V8 Wednesday, July 11, 12
  • 47.
    Curious about? • Is logic-less working for us? • Are we DRY? • How much on the client? • Really? is it more than just a blog post? show me the proof Wednesday, July 11, 12
  • 48.
    Is it morethan just a blog post? Wednesday, July 11, 12
  • 49.
    We even forkedit! Wednesday, July 11, 12
  • 50.
    Is it morethan just a blog post? Wednesday, July 11, 12
  • 51.
    We will beopen about how we extend and how we use it. Wednesday, July 11, 12
  • 52.
    Seriously, tell mehow it is helping us build features? Wednesday, July 11, 12
  • 53.
    Features • Data-driven product, 60%-65% of features we do are displays • remaining 30-35% • flows, ajaxy interactions • writes/deletes Wednesday, July 11, 12
  • 54.
    Parallel web-development • Logic less templates, language of UX, web-dev, front-end • DRY, medium for quicker turn-around • Mock JSON, language of front-end and back-end Wednesday, July 11, 12
  • 55.
    Ok, tell mewhich LI pages are in dust! Wednesday, July 11, 12
  • 56.
    •Search App • https://www.linkedin.com/search-fe/group_search? •Profile •College Alumni Pages • https://www.linkedin.com/college/alumni •PYMK • https://www.linkedin.com/people/pymk Wednesday, July 11, 12
  • 57.
    We also are... • Caching templates • Unifying our stack with Javascript • Developing for cross-device • Moving as much as we need, to the client, move as much as we can to JS Wednesday, July 11, 12
  • 58.
    If you watchthis presentation backwards, it’s should be about a normal web- developers’s life! Wednesday, July 11, 12
  • 59.
    we dust! https://github.com/linkedin/dustjs Wednesday, July 11, 12