Please interrupt me. There is a general perception that apps built using HTML, CSS, and JavaScript are slow. (Hint: We are going to change that in

Embed Size (px)

Citation preview

  • Slide 1
  • Slide 2
  • Slide 3
  • Please interrupt me.
  • Slide 4
  • There is a general perception that apps built using HTML, CSS, and JavaScript are slow. (Hint: We are going to change that in this session)
  • Slide 5
  • Because science!
  • Slide 6
  • // The Basics
  • Slide 7
  • Apache Cordova apps are written in HTML, CSS, and JavaScript that can also access native device capabilities.
  • Slide 8
  • Cordova apps are web applications that run inside a native application. This allows you to use HTML, CSS, and JavaScript to build your app while still having access to your devices hardware capabilities! Native Wrapper Your JavaScript App Cordova Plugin JS API
  • Slide 9
  • What does it mean for something to be fast and responsive?
  • Slide 10
  • Interaction Classes
  • Slide 11
  • What we care about!
  • Slide 12
  • Methodology
  • Slide 13
  • Slide 14
  • 1. The Webview Tax 2. Document Object Model (DOM) 3. Images 4. Animation 5. Garbage Collection 6. UI Controls
  • Slide 15
  • // The Webview Tax
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • // Document Object Model (DOM)
  • Slide 27
  • Slide 28
  • Slide 29
  • Bad Alpha Zeta Tao Epsilon
  • Slide 30
  • Good Alpha Zeta Tao Epsilon
  • Slide 31
  • Slide 32
  • Layout Thrashing
  • Slide 33
  • Slide 34
  • Slide 35 = 0; i--) { b.children[i].style.left = b.children[i].offsetLeft + "px"; b.children[i].style.top = b.childre">
  • Bad for (var i = b.children.length - 1; i >= 0; i--) { b.children[i].style.left = b.children[i].offsetLeft + "px"; b.children[i].style.top = b.children[i].offsetTop + "px"; }
  • Slide 36
  • Good for (var i = b.children.length - 1; i >= 0; i--) { topPx[i] = b.children[i].offsetTop; leftPx[i] = b.children[i].offsetLeft; } for (var i = b.children.length - 1; i >= 0; i--) { b.children[i].style.left = leftPx[i] + "px"; b.children[i].style.top = topPx[i] + "px"; }
  • Slide 37
  • Fast List Scrolling
  • Slide 38
  • Slide 39
  • Memory Usage: Virtualized List vs. Non-Virtualized List
  • Slide 40
  • Use virtualization When working with large amounts of data, only work with the data you need to display content on the screen. (Popular control frameworks like WinJS, Ionic, Onsen UI, Kendo UI and others help handle this for you.)
  • Slide 41
  • // Images
  • Slide 42
  • Gradients
  • Slide 43
  • Slide 44
  • Slide 45
  • Bad.css_gradient { background: -webkit-linear-gradient(top,rgb(84, 1, 1),rgb(0, 84, 119)); /*Safari 5.1-6*/ background: -o-linear-gradient(top,rgb(84, 1, 1),rgb(0, 84, 119)); /*Opera 11.1-12*/ background: -moz-linear-gradient(tp,rgb(84, 1, 1),rgb(0, 84, 119)); /*Fx 3.6-15*/ background: linear-gradient(top, rgb(84, 1, 1),rgb(0, 84, 119)); /*Standard*/ }
  • Slide 46
  • Good.image_gradient { background: url('../images/gradient.png'); }
  • Slide 47
  • // Animation
  • Slide 48
  • Setting Element Position
  • Slide 49
  • Slide 50
  • Slide 51
  • Bad @keyframes bobble { 0% { left: 50px; animation-timing-function: ease-in; } 50% { left: 50px; top: 50px; animation-timing-function: ease-out; } 100% { left: 50px; top: 40px; }
  • Slide 52
  • Good @keyframes bobble { 0% { transform: translate3d(50px, 40px, 0px); animation-timing-function: ease-in; } 50% { transform: translate3d(50px, 50px, 0px); animation-timing-function: ease-out; } 100% { transform: translate3d(50px, 40px, 0px); }
  • Slide 53
  • CSS vs. JavaScript
  • Slide 54
  • Slide 55
  • Slide 56
  • // Garbage Collection
  • Slide 57
  • Slide 58
  • Slide 59
  • Slide 60
  • Bad function createElements() { for (var i = 0; i < 100; ++i) { var xBtn = document.createElement('button'); xBtn.setAttribute('value', 'AA'); xBtn.addEventListener('click', hi, false); containerDiv.appendChild(xBtn); xBtn = null; } function clearElements() { containerDiv.innerHTML = ""; }
  • Slide 61
  • Good function createElements() { for (var i = 0; i < 100; ++i) { var xBtn = document.createElement('button'); xBtn.setAttribute('value', 'AA'); xBtn.addEventListener('click', hi, false); containerDiv.appendChild(xBtn); xBtn = null; } function clearElements() { var els = containerDiv.childNodes; for (var i = 0; i < els.length; i++) { els[i].removeEventListener('click', hi, false); containerDiv.removeChild(els[i]); }
  • Slide 62
  • Minimize Unnecessary Event Listeners
  • Slide 63
  • /* bad *//* good */
  • Slide 64
  • Lets say you want to listen to a click event on the elements with the id value of one, two, three, four, and five. Note: They share a common parent with the theDude element!
  • Slide 65
  • Slide 66
  • Slide 67
  • Bad // ONE FUNCTION FOR EACH EVENT LISTENER for (i = 0; i < 100; i++){ img[i].addEventListener("click", function clickListener(e) { var clickedItem = e.target.id; alert("Hello " + clickedItem); }); }
  • Slide 68
  • Good var theParent = document.querySelector("#theDude"); theParent.addEventListener("click", doSomething, false); function doSomething(e) { if (e.target !== e.currentTarget) { var clickedItem = e.target.id; alert("Hello " + clickedItem); } e.stopPropagation(); }
  • Slide 69
  • Pay Attention to Memory Leaks
  • Slide 70
  • Slide 71
  • Slide 72
  • Bad // el is in the global scope, so it persists with the document var el; function doSomething() { el = document.createElement('div'); parent.appendChild(el); } function empty() { parent.innerHTML = ""; }
  • Slide 73
  • Good // el is in the local scope, so expires with the function function doSomething() { var el = document.createElement('div'); parent.appendChild(el); } function empty() { parent.innerHTML = ""; }
  • Slide 74
  • // UI Controls
  • Slide 75
  • Fast Clicking
  • Slide 76
  • Slide 77
  • Slide 78
  • Slide 79
  • Slide 80
  • Practical Advice (1/3)
  • Slide 81
  • Practical Advice (2/3)
  • Slide 82
  • Practical Advice (3/3)
  • Slide 83