Using Components to Build Native-Quality HTML5 Apps


Published on

A presentation for HTML5 Dev Conf, San Francisco, April 2013

Published in: Technology
  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide
  • Hi, my name is Gray, and I’m a lead member of Enyo,a JavaScript application framework for creating native-quality mobile and desktop apps using web technologies.
  • Enyo is fairly new, so we’ve been knocking on a lot of doors, meeting with a lot of people, getting the word out about Enyo.My colleague asked me, do you think Twitter needs to spend this much time promoting Bootstrap?That really made me think, why is it so hard to get the word out about Enyo? What are we doing wrong?
  • But then I thought about it…Bootstrap is an awesome library for creating beautiful webpages.But in 2012, developers don’t have to be convinced that it’s possible to create beautiful webpages.
  • Enyo, on the other hand, is a framework for creating native-quality apps using the web stack.High-quality user experiences that people expect from native apps.And in 2012, we still have to convince people it’s possible to create native-quality apps on web.
  • And some of our friends in the Valley aren’t doing us any favorsSo it’s sometimes an uphill battle
  • But here’s the thing:We know it’s possible, because we’ve already done it Enyo powered a slew of core applications for the HP Touchpad, built with nothing more than HTML, JS, and CSSalong with thousands other 3rd-party applications
  • And here’s the thing: Even though the Touchpad’s apps were built using web technologies, they weren’t being compared to web pagesThey were being compared to native applications, their iOS and Android counterparts
  • In fact, Enyo was born out of need to givedevelopers a toolkit that allowed them tocreatehigh-performing, touch-friendly interfaces on the web stack, with consistent look-and-feel, without having to reinvent the wheelfor every app
  • There are a lot of frameworks doing great work around data modeling, data-binding, and making it easy to keep views in sync with their data.That’s awesome, but the problem is that most of these frameworks use HTML templating as their view layer.HTML templates are a great solution for formatting data into content-based viewsBut native-quality applications tend to require rich, interactive controls, like this range slider– or pickers, sliders, menus, panels, lists– any number of higher-level above the simple form controls provided by HTML.Clearly templating alone isn’t a great solution for getting there– having to build the slider into your template each time you need one would be tedious.
  • So at this point, you may be thinking, “of course you wouldn’t try to build a slider into your template”, you’d just go grab a jQuery plugin for thatAnd true, libraries like jQuery Mobile and Bootstrap are great solutions to adding interactive controls to webpages
  • But consider a typical native application like the Facebook app on your phone.Since native apps are long-lived, instead of loading a new page for each view, the app needs to dynamically create and transition new views onto screen, which may contain lots of interactive components that need to get hooked up, and discard the views, removing them from the DOM when they are no longer needed.This results in a lot of burden placed on the developer to come up with a sensible application structure and supply all the code for managing the lifecycle of the views– jQuery alone doesn’t attempt to solve that problem.
  • And to be able to compete with those platforms, it required us to rethink how to go about developing applications on the web stack.
  • So here’s the grand reveal, our solution to these challenges: Components.
  • When we talk about components, the most important point is the concept of encapsulation.The idea is that for a given chunk of application functionality:We take the markup required to create the viewAny event handling requiredAny unique logic for the component to perform its dutyAnd any special initialization or cleanup required to mange its lifecycleAnd we draw a box around it; we encapsulate all of that in a JavaScript object that knows how to create, render, and destroy itself, and we interact with it through a well-defined APINow, instead of working with amorphous chunks of DOM cobbled together with messy JavaScript, we start working with self-contained objects with well defined interfacesAnd if that sounds familiar, it’s what we all learned in computer science courses in college: about decomposing large problems into smaller pieces, drawing functional boundaries around them, hiding implementation details, and working with well-defined interfaces. Through components, we bring a fully object-oriented programming model that we feel the web needs to compete with native platforms.
  • In case that was a little abstract, let’s walk through a simple example: A typical sliderFirst, let’s take the markup required to create a slider: say we need these fourdivs to create the DOM structure, along with some CSS specified in an associated stylesheet.In Enyo, we actually use a declarative syntax to capture static DOM inside of our JS components using nested JS object literals like this, which turn out to be a nice, readable syntax for capturing view structure.Next, let’s think about lifecycle; when we create and render a new Slider, we might want to initialize the knob position with a value passed in from the constructor; that would be done here.In order for the slider to move when the user taps or drags his finger, we’ll need to specify event handlers that react to those events, update state, and apply CSS to move the knobFinally, we want to think about the public API for this component; A slider would want to provide a “value” property that allows the developer to programmatically set the value slider positionSo, all of this Slider-specific implementation would get captured in a sub-class of our base Component class, which knows how to take the declarative view, render it into the DOM, and hook up event handlers.
  • Once we’ve done that, we now have a new Slider class, and we can stamp out as many new instances as we like.
  • Using the same technique, we can provide a whole toolkit of self-contained, reusable building blocks with well-defined API’s for creating native-quality applicationsBut if we stopped there, a component-based framework like Enyo might be little more than a great framework for creating widget librariesBut to us, components are much more, because we can allow components to define their view not only in terms of raw HTML, but also in terms of other components
  • Let’s take a look at what that would look likeLet’s say we have a really simple copmonent: A Label, whose API takes a content string and simply renders that into a DOMAnd we combine that with another component: An IntegerLabel, which is similar, but renders a number into the divBy combining those two, we can create a brand new component called a “ValueLabel” – not really interesting yetBut we can take that ValueLabel component, combine it with a Slider, and create a “LabeledSlider”The implementation of the LabeledSlider can have logic to catch slider change events and automatically update the ValueLabel used inside, all hidden behind a nice APINow, say we had an array of attribute names and values; we could pass that into a new component that combines a Groupbox component with a few of these LabeledSliders, and now we have an AttributeView, which simply takes an array reference and allows editing the values through the slidersHopefully you start to see application structure starting to take form…
  • If we continue, we could combine our AttributeView with a couple of other higher-level components created the same way, and arrive at something like a “ContactDetailView” shown here, which is really starting to look like an appNow, the cool thing here is that the ContactDetailView is now a fully encapsulated component itself, no different than the slider.
  • So just like we could instantiate and stamp out a bunch of instances of the slider, we can do the exact same thing with our ContactDetailViewSo you see, it becomes a very blurry line between what’s a UI widget, and what’s a higher-level app view– they’re all components with the exact same semantics, which we find very elegant.
  • And what I want to stress here is that as we go through the process of breaking down our app into reusable pieces, we very quickly get away from working at the raw HTML levelA view like this might be composed of these 4 pieces… … …And it’s only at the very lowest level that we worry about the actual HTML and CSS required to create the view; beyond that we’re working with building blocks with much more meaningful semantics
  • This is my last example of how much a component model can simplify native-quality app developmentIt turns out that smooth scrolling lists, with hundreds or even thousands of items are simply a reality when building native apps that you can’t avoidConsider email inboxes or contact lists or news feeds – But the reality is that smooth scrolling infinite lists are very difficult to do well on the web stack, and especially on mobile devicesFirst of all, creating thousands of elements directly into the DOM is slow and resource intensive, and a lot of mobile browsers will simply run out of memory or crashPlus, asking mobile browsers to move all that content is often results in poor scrolling performance
  • To deal with these problems, inEnyo we provide a high-performance List component that uses a flyweight pattern that keeps only a small subset of the actual list items rendered into the DOM at any given timeOn the JavaScript side, we keep only one template component in memory, and use that to stamp out list items into the DOMWe do this in two pages, enough to provide enough scrolling runway while keeping a small memory footprint and low workload on the scroller which needs to dynamically move the content as the user drags his fingerAs the top page is scrolled out of the viewport and the second page is fully on screen, we reposition the first page below the second, and trigger another page rendering, which provides the next components that will be scrolled into viewAll of this complexity happens in real time as the list is scrolling
  • Now, the beauty is that since the List is a component just like any other, we can place it into any view that needs a list, and all the complexity needed to provide native-like smooth scrolling is hidden behind the list and its well-defined APIWhat’s even better is that we can hand the List any compnents to serve as the flyweight template, using the same declarative syntax we use for all other compositionAnd since all components have a common API for rendering and destroying themselves, we can literally give the list any component, even the ContactDetailView we just created, and get an infinite scrolling list that rivals native applications
  • So, are you sold yet?Hopefully you’ve gotten an idea of why we think the web needs an object-oriented component model to really compete with native platforms for application development. And we’re certainly not the only people thinking about this… You may have heard of the W3C initiatve around Web-Components, which is aiming to drive a similar component encapsulation model deeper into the web standards, and we’re really eagerly watching that space.But there’s one piece you may still be wondering about– why we’re even bothering to achieve native quality apps on the webAtwebOS, we fundamentally believe in a world where our apps, our data, and our content aren’t locked to devicesWe think users want to access all of that content, no matter where they’re at or what device they choose to use– through
  • Using Components to Build Native-Quality HTML5 Apps

    1. 1. USING COMPONENTS TO BUILDNative-Quality HTML5 AppsGray Norton, Enyo originally authored by Kevin Schaaf (@kevinpschaaf)
    2. 2. HI.
    4. 4. CSSJSWebpages✔
    5. 5. Native-QualityApps?CSSJS
    8. 8. TEMPLATES: NOT ENOUGH?Content-based Views TemplatesRich, Interactive Controls
    13. 13. FunctionsPropertiesEventsAPIMarkup:Event handling:Logic / state:ENCAPSULATELifecycle management:
    14. 14. SLIDEREXAMPLE:
    15. 15. Markup Lifecycle Event Handling Logic/APILifecycle management:Event handling:State / Logic:Markup:Markup:
    16. 16. new Slider({value:20});new Slider({value:20});new Slider({value:20});new Slider({value:20});new Slider({value:20});
    18. 18. +LabelLabelAPI: setContent()IntegerLabelAPI: setValue() Label: 20ValueLabelAPI: setContent()setValue()Label: 20ValueLabelAPI: setContent()setValue()SliderAPI: setValue()++LabeledSliderAPI: setLabel()setValue()LabeledSliderAPI: setLabel()setValue()GroupboxAttributeViewAPI: setAttributes()
    19. 19. AttributeViewAPI: setAttributes()+ ContactDetailViewAPI: setContactModel()
    20. 20. new ContactDetailView({contactModel:m});new ContactDetailView({contactModel:m});new ContactDetailView({contactModel:m});new ContactDetailView({contactModel:m});new ContactDetailView({contactModel:m});
    21. 21. ContactDetail:AttributeView:LabeledSlider:Slider:
    22. 22. LISTEXAMPLE:
    23. 23. ListViewportPage 0Page 1Render page0Render page1JavaScript: DOM:Render page0
    27. 27. HTML TEMPLATES
    28. 28. <template id="commentTemplate"><div><img src=""><div class="comment"></div>…</div></template>var t = document.querySelector("#commentTemplate");someElement.appendChild(t.content.cloneNode());
    30. 30. <element extends="button" name="x-fancybutton” constructor=“FancyButton”><template><style scoped>@host { display: contents; }div.fancy {…}</style><div class="fancy"><content></content></div><script>FancyButton.prototype.fancify = function() { … };this.lifecycle({ inserted: this.doSomething(); });</script></template></element><button is=“x-fancybutton”>Click Me!</button>
    32. 32. <link rel="components" href=”my-components.html">
    33. 33. SO…WHY AGAIN?
    34. 34. USING COMPONENTS TO BUILDNative-Quality HTML5 AppsGray Norton, Enyo