The UI is an Application

The UI is an Application

Presented at Dutch PHP Conference on June 26, 2015.

The UI is no longer just a ragtag collection of templates, scripts & styles shoehorned in alongside "real" application code, but is now a rich, complex piece of software in and of itself.

We have a de facto standard language for UI development in JavaScript, yet too often our UI code remains tangled up in hamstrung templating languages, CSS preprocessors and whatever language or framework our back end happens to be built with.

In this talk we'll explore what happens when you treat your UI as a first class citizen, separating it from the rest of your app and replacing traditional templates & CSS with the real programming language you already know: JavaScript.

D8de178c08fe406eceeba711709ed3da?s=128

Ben Smithett

June 26, 2015
Tweet

Transcript

  1. Application The UI is an

  2. who am i? Ben Smithett Front End Dev @ @bensmithett

    / bensmithett.com
  3. I know nothing about PHP

  4. complex application In 2015, a web app’s user interface is

    a
  5. web designer The UI used to be the domain of

    the
  6. More complex interactivity Ajax Preprocessors & build tooling

  7. Front end developer The UI is now the domain of

    the
  8. javascript The language of UI development is

  9. • Application logic: written in JS • Routing: written in

    JS • Templates: compiled by JS • CSS: pre- and post-processed by JS • Build tooling: powered by JS • Compile-to-JS languages: …it’s all JS
  10. all the way down UI development for the web is

    JavaScript
  11. app models controllers views

  12. app models controllers views

  13. app models controllers views config routes

  14. app models controllers views config routes API pages

  15. config routes API pages app models controllers views API pages

  16. config routes API pages app models controllers views API pages

    assets
  17. config routes API pages app models controllers views API pages

    assets images
  18. config routes API pages app models controllers views API pages

    assets images icons sprites
  19. assets webfonts config routes API pages app models controllers views

    API pages images icons sprites
  20. assets webfonts config routes API pages app models controllers views

    API pages images icons sprites stylesheets
  21. assets webfonts config routes API pages app models controllers views

    API pages images icons sprites stylesheets vars mixins
  22. assets webfonts config routes API pages app models controllers views

    API pages images icons sprites stylesheets vars mixins javascripts
  23. assets webfonts config routes API pages app models controllers views

    API pages images icons sprites stylesheets vars mixins javascripts models controllers views
  24. assets webfonts config routes API pages app models controllers views

    API pages images icons sprites stylesheets vars mixins javascripts models controllers views templates
  25. assets webfonts config routes API pages app models controllers views

    API pages images icons sprites stylesheets vars mixins javascripts models controllers views templates router
  26. assets webfonts config routes API pages app models controllers views

    API pages images icons sprites stylesheets vars mixins javascripts models controllers views templates router js app routes
  27. assets webfonts config routes API pages app models controllers views

    API pages images icons sprites stylesheets vars mixins javascripts models controllers views templates router js app routes vendor
  28. assets webfonts config routes API pages app models controllers views

    API pages images icons sprites stylesheets vars mixins javascripts models controllers views templates router js app routes vendor tooling
  29. assets webfonts config routes API pages app models controllers views

    API pages images icons sprites stylesheets vars mixins javascripts models controllers views templates router js app routes vendor tooling back end tests
  30. assets webfonts config routes API pages app models controllers views

    API pages images icons sprites stylesheets vars mixins javascripts models controllers views templates router js app routes vendor tooling back end tests UI tests
  31. assets webfonts config routes API pages app models controllers views

    API pages images icons sprites stylesheets vars mixins javascripts models controllers views templates router js app routes vendor tooling back end tests UI tests deployment
  32. assets webfonts config routes API pages app models controllers views

    API pages images icons sprites stylesheets vars mixins javascripts models controllers views templates router js app routes vendor tooling back end tests UI tests deployment asset pipeline
  33. this is insane!

  34. assets webfonts config routes API pages app models controllers views

    API pages images icons sprites stylesheets vars mixins javascripts models controllers views templates router js app routes vendor tooling back end tests UI tests deployment asset pipeline
  35. a first class citizen Today’s frameworks don’t treat the UI

    as
  36. “real” application code Today’s frameworks don’t treat the UI as

  37. There has to be a better way…

  38. assets webfonts config routes API pages app models controllers views

    API pages images icons sprites stylesheets vars mixins javascripts models controllers views templates router js app routes vendor tooling back end tests UI tests deployment asset pipeline
  39. API app config api endpoint routes models controllers tooling back

    end tests deployment ui app images stylesheets webfonts config vars mixins functions javascripts models controllers views templates router vendor tests asset pipeline
  40. browser PHP api APP static host javascript UI APP

  41. • Load JS file • Make API request • Generate

    initial HTML
  42. None
  43. break your javascript Network conditions, browser extensions and plain old

    bugs can (and will)
  44. real html Search engine crawlers prefer

  45. browser PHP api APP static host javascript UI APP

  46. browser PHP api APP node.js javascript UI APP

  47. browser PHP api APP node.js javascript UI APP

  48. browser PHP api APP node.js javascript UI APP

  49. browser PHP api APP node.js javascript UI APP real <html>

  50. browser PHP api APP node.js javascript UI APP real <html>

    static host javascript UI APP
  51. browser PHP api APP node.js javascript UI APP real <html>

    static host javascript UI APP
  52. Embracing JavaScript as the language of UI development enables a

    focused, DRY codebase and a slick, yet fault- tolerant, end user experience.
  53. templates & styles You’re probably not authoring in JavaScript

  54. template? What is a

  55. "<div>" + "<h1>" + "Hello " + name + "!"

    + "</h1>" + "<div>"
  56. function A template is a Data in. HTML string out.

  57. function template (name) { return "<div>" + "<h1>" + "Hello

    " + name + "!" + "</h1>" + "<div>" }
  58. <div> <h1>Hello {{ name }}!</h1> </div>

  59. function template (name) { return "<div>" + "<h1>" + "Hello

    " + name + "!" + "</h1>" + "<div>" }
  60. embedded languages & logic-less templates Different kinds of string templates:

  61. embedded language template - php <div> <?php if ($conference ==

    "DPC"): ?> Welcome to <?= $conference ?>! <?php else: ?> Wrong conference! <?php endif; ?> </div>
  62. embedded language template - ERB <div> <% if @conference ==

    "DPC" %> Welcome to <%= @conference %>! <% else %> Wrong conference! <% end %> </div>
  63. embedded language template - EJS <div> <% if (conference ===

    "DPC") { %> Welcome to <%= conference %>! <% } else { %> Boooo <% } %> </div>
  64. <div> <% if @conference == "DPC" %> <h1>DPC Speakers</h1> <ul>

    <% @speakers.each |speaker| do %> <li> <img src="<%= speaker.avatar %>" /> <strong><%= speaker.name %></strong> </li> <% end %> </ul> <% elsif @conference && @conference.name %> <strong class="error"> No speakers found for <%= @conference.name %>! </strong> <% end %> </div>
  65. <?php get_header(); ?> <div id="content" class="narrowcolumn"> <?php $querystr = "

    SELECT $wpdb->posts.* FROM $wpdb->posts, $wpdb->postmeta WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id AND $wpdb->postmeta.meta_key = 'tag' AND $wpdb->posts.post_status = 'publish' ORDER BY $wpdb->posts.post_date DESC "; $pageposts = $wpdb->get_results($querystr, OBJECT); ?> <?php if ($pageposts): ?> <?php global $post; ?> <?php foreach ($pageposts as $post): ?> <?php setup_postdata($post); ?> <div class="post" id="post-<?php the_ID(); ?>"> <h2><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"> <?php the_title(); ?></a></h2> <small><?php the_time('F jS, Y') ?> <!-- by <?php the_author() ?> --></small> <div class="entry"> <?php the_content('Read the rest of this entry »'); ?> </div> <p class="postmetadata">Posted in <?php the_category(', ') ?> | <?php edit_post_link('Edit', '', ' | '); ?> <?php comments_popup_link('No Comments »', '1 Comment »', '% Comments »'); ?></p> </div> <?php endforeach; ?> <?php else : ?> <h2 class="center">Not Found</h2> <p class="center">Sorry, but you are looking for something that isn't here.</p> <?php include (TEMPLATEPATH . "/searchform.php"); ?> <?php endif; ?> </div> <?php get_sidebar(); ?> Source: Wordpress Codex
  66. logic-less templates! We revolted against the spaghetti code enabled by

    embedded language templates No more logic allowed in Views!
  67. <div> Welcome to {{conference}}! </div>

  68. Are a lie Logic-less templates

  69. <div> {{#conference}} <h1>DPC Speakers</h1> <ul> {{#speakers}} <li> <img src="{{avatar_url}}" />

    <strong>{{speaker_name}}</strong> </li> {{/speakers}} {{^speakers}} <li>No speakers found!</li> {{/speakers}} </ul> {{/conference}} </div>
  70. hamstrung languages We’re writing our views with

  71. Is string templating useful in 2015?

  72. <div> Welcome to {{conference}}! </div>

  73. <div> Unread: {{unread_message_count}} <h1>Send message:</h1> <textarea></textarea> </div>

  74. stateful The DOM is

  75. String templates aren’t the best tool for expressing UI structure

    in web apps.
  76. None
  77. pure javascript React components are written in

  78. React.createClass({ render () { return ( React.createElement('div', {}, React.createElement('h1', {},

    “Hi DPC!” ) ) ) } })
  79. React.createClass({ render () { return ( React.createElement('div', {}, React.createElement('h1', {},

    “Hi DPC!” ) ) ) } }) // <div> // <h1> // Hi DPC! // </h1> // </div>
  80. React.createClass({ render () { return ( <div> <h1> Hi DPC!

    </h1> </div> ) } })
  81. React.createClass({ render () { return ( <div> <h1> Hi DPC!

    </h1> </div> ) } }) React.createElement('div', {}, React.createElement('h1', {}, “Hi DPC!” ) )
  82. <ul> { this.props.speakers ? this.props.speakers.map((speaker) => { var name =

    speaker.name.toUpperCase() return <li>{name}</li> }) : <li>No speakers found!</li> } </ul>
  83. the virtual dom abstracts away the hard work of syncing

    your views with the stateful DOM
  84. virtual dom <div> Unread: <span id='count'>4</span> <h1>Send message:</h1> <textarea></textarea> </div>

  85. virtual dom real dom <div> Unread: <span id='count'>4</span> <h1>Send message:</h1>

    <textarea></textarea> </div> <div> Unread: <span id='count'>3</span> <h1>Send message:</h1> <textarea></textarea> </div>
  86. virtual dom real dom <div> Unread: <span id='count'>4</span> <h1>Send message:</h1>

    <textarea></textarea> </div> <div> Unread: <span id='count'>3</span> <h1>Send message:</h1> <textarea></textarea> </div> document.querySelector('#count').innerHTML('4') minimum possible imperative update
  87. fewer moving parts fewer things to learn No template engine

    required
  88. const Header = React.createClass({ render () { return ( <div>

    <h1> Hi DPC! </h1> </div> ) } }) React.renderToString(<Header />) // "<div><h1>Hi DPC!</h1></div>"
  89. tightly coupled View logic & structure are

  90. <button class="fav" id="12345">Favorite this</button> $('.fav').on('click', function (event) { Api.favorite(event.target.id) })

  91. <button class="fav" id="12345">Favorite this</button> $('.fav').on('click', function (event) { Api.favorite(event.target.id) })

  92. const FavButton = React.createClass({ handleClick () { Api.favourite(this.props.id) }, render

    () { return ( <button onClick={this.handleClick}> Favorite this </button> ) } })
  93. pure javascript components Replace templates & separated logic with

  94. css What about

  95. everybody uses a preprocessor

  96. i ❤

  97. .btn { color: #f00; width: 200px; } .btn:hover { background:

    #00f; } .col-1 { width: 8.33333%; } .col-2 { width: 16.66667%; }
  98. .btn { color: #f00; width: 200px; } .btn:hover { background:

    #00f; } .col-1 { width: 8.33333%; } .col-2 { width: 16.66667%; } .btn { color: $red; width: 200px; &:hover { background: $yellow; } } @for $i from 1 through 12 { .col-#{$i} { width: 100% / ($i * 12); } }
  99. variables conditionals loops functions math string manipulation JavaScript already has

  100. objects with keys & values JavaScript great for working with

  101. var myStyles = { color: colors.red, backgroundColor: signedInUser ? colors.green

    : colors.grey, backgroundImage: CDNPathFor('forest_bg.png'), width: Math.round(document.body.offsetWidth / 2) + 'px' }
  102. var totalCols = 12 var gridColClasses = {} for (var

    i = 1; i <= totalCols; i++) { gridColClasses['col-' + i] = { width: ((100 / totalCols) * i) + '%' } }
  103. var totalCols = 12 var gridColClasses = {} for (var

    i = 1; i <= totalCols; i++) { gridColClasses['col-' + i] = { width: ((100 / totalCols) * i) + '%' } }
  104. import createGrid from 'grid' var gridStyles = createGrid(12)

  105. mature fully featured well understood JavaScript is a more language

    than the CSS preprocessors
  106. real css… … great, but browsers still need

  107. inline styles

  108. None
  109. why not use inline styles? • Because it isn’t DRY!

  110. <div style="border: 2px solid #0f0; height: 100px; width: 100px; float:

    left;"> <img src="..." /> </div> <div style="border: 2px solid #0f0; height: 100px; width: 100px; float: left;"> <img src="..." /> </div> <div style="border: 2px solid #0f0; height: 100px; width: 100px; float: left;"> <img src="..." /> </div>
  111. <div class="thumb"> <img src="..." /> </div> <div class="thumb"> <img src="..."

    /> </div> <div class="thumb"> <img src="..." /> </div>
  112. don’t write the same html twice! How to not repeat

    yourself:
  113. var Thumb = React.createClass({ render () { return ( <div

    className='thumb'> <img src={this.props.src} /> </div> ) } })
  114. <Thumb src="a.jpg" /> <Thumb src="b.jpg" /> <Thumb src="c.jpg" />

  115. var Thumb = React.createClass({ render () { return ( <div

    className='thumb'> <img src={this.props.src} /> </div> ) } })
  116. var thumbStyles = { border: '2px solid #0f0', height: '100px',

    width: '100px', float: left } var Thumb = React.createClass({ render () { return ( <div className='thumb'> <img src={this.props.src} /> </div> ) } })
  117. var thumbStyles = { border: '2px solid #0f0', height: '100px',

    width: '100px', float: left } var Thumb = React.createClass({ render () { return ( <div style={thumbStyles}> <img src={this.props.src} /> </div> ) } })
  118. don’t write the same html twice! No, really…

  119. why not use inline styles? • Because it isn’t DRY!


    It can be, if you stop writing the same HTML multiple times
  120. why not use inline styles? • Because it isn’t DRY!


    It can be, if you stop writing the same HTML multiple times • Performance?
  121. why not use inline styles? • Because it isn’t DRY!


    It can be, if you stop writing the same HTML multiple times • Performance?
 Maybe… but probably not enough for you to worry about!
  122. But CSS syntax is kinda nice…

  123. PostCSS + Autoprefixer

  124. react-style var styles = StyleSheet.create` .foo { color: red; background-color:

    white; } ` github.com/js-next/react-style
  125. github.com/css-modules

  126. import styles from './profile.css'; var Profile = React.createClass({ render() {

    return <div className={styles.wrapper}> <img className={styles.image} src="..." /> <span className={styles.username}>...</span> </div> } }
  127. In conclusion…

  128. complex application Your user interface is a

  129. javascript The language of UI development is

  130. thanks! @bensmithett