SlideShare ist ein Scribd-Unternehmen logo
1 von 29
Leaving
jsps in the dust
      @vybs
We are pi@linkedIn
front-end
infrastructure
Goal(s)
Site-Scale   +   Site-Speed




In the beginning...
What is the Problem?
Site-Scale       Developer
                  Velocity


         Site-Speed




       But...
Simple things should be
      dead easy
Build Quick, Iterate More
front-end infrastructure
     now became....
Grails   Jruby   Node.js




Static Vs Dynamic
Anyone notice a bad
    pattern?
Do once, Do the same
 twice, Do the same
      thrice...!
How does this work
effectively in mobile?
Still building heavy pages
          not apps
We created a few more
  problems indeed!
How did we solve them?
Unification

• Javascript Templates, CDN caching
 • Write once
• JSON for data
 • One Standard
• Event-ed Server as JSON Aggregator + JS
  V8 engine
 • Scale once
JavaScript templates


• Evaluated tons, handlebars, dust, mustache
• Good: Simple, less logic, 4KB, precompiled
  to javascript, performance is a feature
• Bad: None are mature enough, i18n/
  formatters not out of the box
_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);!
      }!



           Hello James! You have 2 new
              messages from Jim, Eran!
Dust - *less logic
• Simple, DRY
 • loops, conditionals, partials, inheritance
    {#people}
     {>”/path/degree_icon_{distance}”/}
    {/people}
Dust
• Client Helpers for extensions, reusability
 • Rendering logic, math, i18n
   • @if, @select, @lte, @ceil, @i18n,
       @form
{#people}
    <li class="card
     {@select key=“distance”}
      {@lte value=“1”/} {@i18n text=“first degree”/}
      {@gt value=“1”/} {@i18n text=“second degree”/}
     {/select}
   </li>
{/people}
! on client
• Server side precompiled to JS
 • Rendering times on client snappy
! on client
• Server side processed helper tags
 • auto-generate template dependencies
{#people}
     {“>degree_icon”/}
{/people}
! on client
• Dust Preprocessed helper tags
 • leverage JVM based i18n, formatting and A/B
        testing
 • creates template driven, context based JSON
 Server Source template
 {#people}
     {@ss.fmt key=”fmt_name” type=“name” value=”{name}”/}
 {/people}


                                     “people” : [{ “name” : “Joe Jada”,
 Client template/ js                               “fmt_name” : “Joe J”,

  {#people}                uses                    “distance” : “2”
                                                },{ “name”: ”Jade Pink”
    {fmt_name}                                      “fmt_name” : “Jade P”,
  {/people}                                         “distance” : “1”}
                                                ]
                                          }
! on client

• No javascript, SEO pages
• Seamless rendering of dust on the server using
  V8
Browser                     CDN          caching
                                                               content delivery




linkedin.com




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




      apps          Page    Module    Module


       data layer   JSON    JSON       JSON
linkedin.com/people/pymk
we dust!
https://github.com/linkedin/dustjs
  https://github.com/linkedin/Lu
https://github.com/linkedin/inject

Weitere ähnliche Inhalte

Was ist angesagt?

Building with JavaScript - write less by using the right tools
Building with JavaScript -  write less by using the right toolsBuilding with JavaScript -  write less by using the right tools
Building with JavaScript - write less by using the right tools
Christian Heilmann
 
Using gzip to speed up performance
Using gzip to speed up performanceUsing gzip to speed up performance
Using gzip to speed up performance
Vinod Pabba
 

Was ist angesagt? (20)

Web Components at Scale, HTML5DevConf 2014-10-21
Web Components at Scale, HTML5DevConf 2014-10-21Web Components at Scale, HTML5DevConf 2014-10-21
Web Components at Scale, HTML5DevConf 2014-10-21
 
Preparing your web services for Android and your Android app for web services...
Preparing your web services for Android and your Android app for web services...Preparing your web services for Android and your Android app for web services...
Preparing your web services for Android and your Android app for web services...
 
Web Optimisation
Web OptimisationWeb Optimisation
Web Optimisation
 
Type URL, Enter, and Then …
Type URL, Enter, and Then …Type URL, Enter, and Then …
Type URL, Enter, and Then …
 
Pinkoi Platform
Pinkoi PlatformPinkoi Platform
Pinkoi Platform
 
Building with JavaScript - write less by using the right tools
Building with JavaScript -  write less by using the right toolsBuilding with JavaScript -  write less by using the right tools
Building with JavaScript - write less by using the right tools
 
웹을 지탱하는 차세대 기술 @한국웹20주년 컨퍼런스
웹을 지탱하는 차세대 기술 @한국웹20주년 컨퍼런스웹을 지탱하는 차세대 기술 @한국웹20주년 컨퍼런스
웹을 지탱하는 차세대 기술 @한국웹20주년 컨퍼런스
 
Building high performing web pages
Building high performing web pagesBuilding high performing web pages
Building high performing web pages
 
The rise of Polymer and Web Components (Kostas Karolemeas) - GreeceJS #17
The rise of Polymer and Web Components (Kostas Karolemeas) - GreeceJS #17The rise of Polymer and Web Components (Kostas Karolemeas) - GreeceJS #17
The rise of Polymer and Web Components (Kostas Karolemeas) - GreeceJS #17
 
The latest in site speed: advanced #webperf 2018
The latest in site speed: advanced #webperf 2018The latest in site speed: advanced #webperf 2018
The latest in site speed: advanced #webperf 2018
 
It is not HTML5. but ... / HTML5ではないサイトからHTML5を考える
It is not HTML5. but ... / HTML5ではないサイトからHTML5を考えるIt is not HTML5. but ... / HTML5ではないサイトからHTML5を考える
It is not HTML5. but ... / HTML5ではないサイトからHTML5を考える
 
Using gzip to speed up performance
Using gzip to speed up performanceUsing gzip to speed up performance
Using gzip to speed up performance
 
HTML5ではないサイトを HTML5へ - Change HTML5 from Not HTML5.
HTML5ではないサイトを HTML5へ - Change HTML5 from Not HTML5.HTML5ではないサイトを HTML5へ - Change HTML5 from Not HTML5.
HTML5ではないサイトを HTML5へ - Change HTML5 from Not HTML5.
 
Familiar HTML5 - 事例とサンプルコードから学ぶ 身近で普通に使わているHTML5
Familiar HTML5 - 事例とサンプルコードから学ぶ 身近で普通に使わているHTML5Familiar HTML5 - 事例とサンプルコードから学ぶ 身近で普通に使わているHTML5
Familiar HTML5 - 事例とサンプルコードから学ぶ 身近で普通に使わているHTML5
 
HTTP 2.0 - Web Unleashed 2015
HTTP 2.0 - Web Unleashed 2015HTTP 2.0 - Web Unleashed 2015
HTTP 2.0 - Web Unleashed 2015
 
Disruptive code
Disruptive codeDisruptive code
Disruptive code
 
Google Polymer Framework
Google Polymer FrameworkGoogle Polymer Framework
Google Polymer Framework
 
Exploring Critical Rendering Path
Exploring Critical Rendering PathExploring Critical Rendering Path
Exploring Critical Rendering Path
 
How to build a web application with Polymer
How to build a web application with PolymerHow to build a web application with Polymer
How to build a web application with Polymer
 
Javascript fatigue, 자바스크립트 피로
Javascript fatigue, 자바스크립트 피로Javascript fatigue, 자바스크립트 피로
Javascript fatigue, 자바스크립트 피로
 

Andere mochten auch

FINAL SHOWCASE
FINAL SHOWCASEFINAL SHOWCASE
FINAL SHOWCASE
jlbentz
 
FINAL SHOWCASE
FINAL SHOWCASEFINAL SHOWCASE
FINAL SHOWCASE
jlbentz
 
Colro Harmonies Showcase
Colro Harmonies ShowcaseColro Harmonies Showcase
Colro Harmonies Showcase
jlbentz
 
personalplc7715
personalplc7715personalplc7715
personalplc7715
P L Chavan
 
Power Point
Power PointPower Point
Power Point
jlbentz
 

Andere mochten auch (17)

Unveiling the newest product of LinkedIn Talent Solutions | Talent Connect An...
Unveiling the newest product of LinkedIn Talent Solutions | Talent Connect An...Unveiling the newest product of LinkedIn Talent Solutions | Talent Connect An...
Unveiling the newest product of LinkedIn Talent Solutions | Talent Connect An...
 
MPI WestField Chapter September Newsletter
MPI WestField Chapter September NewsletterMPI WestField Chapter September Newsletter
MPI WestField Chapter September Newsletter
 
Dust[in]
Dust[in]Dust[in]
Dust[in]
 
Final Showcase
Final ShowcaseFinal Showcase
Final Showcase
 
FINAL SHOWCASE
FINAL SHOWCASEFINAL SHOWCASE
FINAL SHOWCASE
 
FINAL SHOWCASE
FINAL SHOWCASEFINAL SHOWCASE
FINAL SHOWCASE
 
Colro Harmonies Showcase
Colro Harmonies ShowcaseColro Harmonies Showcase
Colro Harmonies Showcase
 
Growthandculture
GrowthandcultureGrowthandculture
Growthandculture
 
Curious case of Dust
Curious case of DustCurious case of Dust
Curious case of Dust
 
Journey@LI
Journey@LIJourney@LI
Journey@LI
 
Differe
DiffereDiffere
Differe
 
Nets S
Nets SNets S
Nets S
 
personalplc7715
personalplc7715personalplc7715
personalplc7715
 
LinkedIn Overview
LinkedIn OverviewLinkedIn Overview
LinkedIn Overview
 
FELIZ CUMPLEBLOG
FELIZ CUMPLEBLOGFELIZ CUMPLEBLOG
FELIZ CUMPLEBLOG
 
Startup DNA: Speed Wins
Startup DNA: Speed WinsStartup DNA: Speed Wins
Startup DNA: Speed Wins
 
Power Point
Power PointPower Point
Power Point
 

Ähnlich wie Leaving jsps in the dust

CouchDB Open Source Bridge
CouchDB Open Source BridgeCouchDB Open Source Bridge
CouchDB Open Source Bridge
Chris Anderson
 
Web Development using Ruby on Rails
Web Development using Ruby on RailsWeb Development using Ruby on Rails
Web Development using Ruby on Rails
Avi Kedar
 
CouchDB at JAOO Århus 2009
CouchDB at JAOO Århus 2009CouchDB at JAOO Århus 2009
CouchDB at JAOO Århus 2009
Jason Davies
 
AngularJS - a radically different way of building Single Page Apps
AngularJS - a radically different way of building Single Page AppsAngularJS - a radically different way of building Single Page Apps
AngularJS - a radically different way of building Single Page Apps
jivkopetiov
 
There's more than web
There's more than webThere's more than web
There's more than web
Matt Evans
 
Hypercubes In Hbase
Hypercubes In HbaseHypercubes In Hbase
Hypercubes In Hbase
George Ang
 
How Signpost uses MongoDB for Tracking and Analytics
How Signpost uses MongoDB for Tracking and AnalyticsHow Signpost uses MongoDB for Tracking and Analytics
How Signpost uses MongoDB for Tracking and Analytics
mattinsler
 

Ähnlich wie Leaving jsps in the dust (20)

Crafting Evolvable Api Responses
Crafting Evolvable Api ResponsesCrafting Evolvable Api Responses
Crafting Evolvable Api Responses
 
Couchdb Nosql
Couchdb NosqlCouchdb Nosql
Couchdb Nosql
 
Practical Use of MongoDB for Node.js
Practical Use of MongoDB for Node.jsPractical Use of MongoDB for Node.js
Practical Use of MongoDB for Node.js
 
Json at work overview and ecosystem-v2.0
Json at work   overview and ecosystem-v2.0Json at work   overview and ecosystem-v2.0
Json at work overview and ecosystem-v2.0
 
Azure for SharePoint Developers - Workshop - Part 2: Azure Functions
Azure for SharePoint Developers - Workshop - Part 2: Azure FunctionsAzure for SharePoint Developers - Workshop - Part 2: Azure Functions
Azure for SharePoint Developers - Workshop - Part 2: Azure Functions
 
CouchDB Open Source Bridge
CouchDB Open Source BridgeCouchDB Open Source Bridge
CouchDB Open Source Bridge
 
ActiveDOM
ActiveDOMActiveDOM
ActiveDOM
 
Web Development using Ruby on Rails
Web Development using Ruby on RailsWeb Development using Ruby on Rails
Web Development using Ruby on Rails
 
OSML and OpenSocial 0.9
OSML and OpenSocial 0.9OSML and OpenSocial 0.9
OSML and OpenSocial 0.9
 
CouchDB at JAOO Århus 2009
CouchDB at JAOO Århus 2009CouchDB at JAOO Århus 2009
CouchDB at JAOO Århus 2009
 
AngularJS - a radically different way of building Single Page Apps
AngularJS - a radically different way of building Single Page AppsAngularJS - a radically different way of building Single Page Apps
AngularJS - a radically different way of building Single Page Apps
 
REST easy with API Platform
REST easy with API PlatformREST easy with API Platform
REST easy with API Platform
 
Responsive Web Design: Clever Tips and Techniques
Responsive Web Design: Clever Tips and TechniquesResponsive Web Design: Clever Tips and Techniques
Responsive Web Design: Clever Tips and Techniques
 
Composable Data Processing with Apache Spark
Composable Data Processing with Apache SparkComposable Data Processing with Apache Spark
Composable Data Processing with Apache Spark
 
JSONSchema with golang
JSONSchema with golangJSONSchema with golang
JSONSchema with golang
 
Socialite, the Open Source Status Feed
Socialite, the Open Source Status FeedSocialite, the Open Source Status Feed
Socialite, the Open Source Status Feed
 
There's more than web
There's more than webThere's more than web
There's more than web
 
Getting started with titanium
Getting started with titaniumGetting started with titanium
Getting started with titanium
 
Hypercubes In Hbase
Hypercubes In HbaseHypercubes In Hbase
Hypercubes In Hbase
 
How Signpost uses MongoDB for Tracking and Analytics
How Signpost uses MongoDB for Tracking and AnalyticsHow Signpost uses MongoDB for Tracking and Analytics
How Signpost uses MongoDB for Tracking and Analytics
 

Kürzlich hochgeladen

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 

Kürzlich hochgeladen (20)

Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 

Leaving jsps in the dust

  • 1. Leaving jsps in the dust @vybs
  • 5. Site-Scale + Site-Speed In the beginning...
  • 6. What is the Problem?
  • 7. Site-Scale Developer Velocity Site-Speed But...
  • 8. Simple things should be dead easy
  • 10. front-end infrastructure now became....
  • 11. Grails Jruby Node.js Static Vs Dynamic
  • 12. Anyone notice a bad pattern?
  • 13. Do once, Do the same twice, Do the same thrice...!
  • 14. How does this work effectively in mobile?
  • 15. Still building heavy pages not apps
  • 16. We created a few more problems indeed!
  • 17. How did we solve them?
  • 18. Unification • Javascript Templates, CDN caching • Write once • JSON for data • One Standard • Event-ed Server as JSON Aggregator + JS V8 engine • Scale once
  • 19. JavaScript templates • Evaluated tons, handlebars, dust, mustache • Good: Simple, less logic, 4KB, precompiled to javascript, performance is a feature • Bad: None are mature enough, i18n/ formatters not out of the box
  • 20. _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);! }! Hello James! You have 2 new messages from Jim, Eran!
  • 21. Dust - *less logic • Simple, DRY • loops, conditionals, partials, inheritance {#people} {>”/path/degree_icon_{distance}”/} {/people}
  • 22. Dust • Client Helpers for extensions, reusability • Rendering logic, math, i18n • @if, @select, @lte, @ceil, @i18n, @form {#people} <li class="card {@select key=“distance”} {@lte value=“1”/} {@i18n text=“first degree”/} {@gt value=“1”/} {@i18n text=“second degree”/} {/select} </li> {/people}
  • 23. ! on client • Server side precompiled to JS • Rendering times on client snappy
  • 24. ! on client • Server side processed helper tags • auto-generate template dependencies {#people} {“>degree_icon”/} {/people}
  • 25. ! on client • Dust Preprocessed helper tags • leverage JVM based i18n, formatting and A/B testing • creates template driven, context based JSON Server Source template {#people} {@ss.fmt key=”fmt_name” type=“name” value=”{name}”/} {/people} “people” : [{ “name” : “Joe Jada”, Client template/ js “fmt_name” : “Joe J”, {#people} uses “distance” : “2” },{ “name”: ”Jade Pink” {fmt_name} “fmt_name” : “Jade P”, {/people} “distance” : “1”} ] }
  • 26. ! on client • No javascript, SEO pages • Seamless rendering of dust on the server using V8
  • 27. Browser CDN caching content delivery linkedin.com UI /JSON Aggregator Static Assets static content V8 js, css, templates apps Page Module Module data layer JSON JSON JSON
  • 29. we dust! https://github.com/linkedin/dustjs https://github.com/linkedin/Lu https://github.com/linkedin/inject

Hinweis der Redaktion

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n