All of the Fasts.
Tree v8 Performance
Tyler Graf
Senior Web Developer familysearch.org

Why Polymer?
Frameworks
(JavaScript)



566KB
132KB
435KB
#useThePlatform
//jquery (28KB)
$('#thing');
//native
document.querySelector('#thing');
//angular 2 (566KB)
this.http.get('/resource')
.subscribe(data => {
// do stuff
});
//native
fetch('/resource')
.then(res=>res.json)
.then(data=>{
// do stuff
});
Web Components
- Shadow DOM
- Custom Elements
- HTML Templates
- HTML Imports
SPEC
(specification)
Shadow DOM
Style Encapsulation
Custom Elements
<my-element></my-element>
HTML Templates
<template>
<header>Title</header>
<section>
<p>Hi, I'm inside a template.</p>
</section>
</template>
HTML Imports
<link rel="import" href="my-element.html">
<link rel="import" href="bower_components/polymer/polymer-element.html">
<link rel="import" href="bower_components/paper-button/paper-button.html">
<dom-module id="my-element">
<template>
<style>
h1 {
color: red;
}
</style>
<h1>Hi</h1>
<p>[[textContent]]</p>
<paper-button>Go</paper-button>
</template>
<script>
class MyElement extends Polymer.Element {
static get is() { return 'my-element'; }
ready() {
super.ready();
this.textContent = "I'm a custom element!";
}
}
// Associate the new class with an element name
customElements.define('my-element', MyElement);
</script>
</dom-module>
<my-element></my-element>
Support

https://webcomponents.org
Lots or shared components
Cons
- Not kitchen sink
- Template bindings
- polyfills
- smaller community
Polymer Progression
Polymer 1 - 40KB
Polymer 2 - 12KB
Polymer 3 - ?KB
webcomponents.js (polyfills) - 25KB
HTML Imports => JS Imports
(ES Modules)


Performance
Page Load Times

Metrics
https://speakerdeck.com/addyosmani/the-browser-hackers-guide-to-instant-loading
Goal
Interactive
< 5s

Average Mobile Device over 3G
Phones are slow!

https://speakerdeck.com/addyosmani/the-browser-hackers-guide-to-instant-loading
Current State
Average Web Page on Mobile
16s
Interactive
19s
Fully loaded
420KB
JS
https://www.doubleclickbygoogle.com/articles/mobile-speed-matters/
Test on Real Phones
Chrome Dev Tools
- Mobile Emulation
- Remote Device
Safari
- Remote Debugging
Web Page Test
Ask Around for Old Phones
PRPL Pattern
- Push minimal code for initial route
- Render the initial route
- Pre-cache using service worker
- Lazy load other routes
Code Splitting
Split code up into each route and only load what's needed.
SPA
single page app

https://developers.google.com/web/fundamentals/performance/prpl-pattern/
Case Study
Perf Profiles
- Philippines 3G
- Australia 3G 1.6Mbps/768Kbps 300ms RTT EC2
- Wasatch User
- California Cable 5Mbps/1Mbps 28ms RTT EC2
- Virginia 3G Mobile
- Virginia 3G 1.6Mbps/768Kbps 300ms RTT Moto G4
- Virginia iPhone
- Virginia LTE 12Mbps/12Mbps 70ms RTT iPhone 6s
Baseline
Philippines 3G - 16.1s
- CDN
- Minified
- gzipped
- http2
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Title</title>
</head>
<body>
<link rel="import" href="my-app.html">
<link rel="import" href="person-card.html">
<link rel="import" href="other-thing.html">
<my-app></my-app>
</body>
</html>
<link rel="import" href="polymer.html">
<link rel="import" href="app-route.html">
<link rel="import" href="app-location.html">
<link rel="import" href="iron-pages.html">
<link rel="import" href="fs-app-path.html">
<link rel="import" href="tree-behavior.html">
<link rel="import" href="tree-help.html">
index.html
my-app.html

Steps
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Title</title>
</head>
<body>
<link rel="import" href="my-app.html">
<link rel="import" href="person-card.html">
<link rel="import" href="other-thing.html">
<link rel="import" href="/elements/tree-pwa/tree-app.html">
<link rel="import" href="/components/polymer/polymer.html">
<link rel="import" href="/components/app-route/app-route.html">
<link rel="import" href="/components/app-route/app-location.html">
<link rel="import" href="/components/iron-location/iron-location.html">
<link rel="import" href="/components/iron-location/iron-query-params.html">
<link rel="import" href="/components/app-route/app-route-converter-behavior.html">
<link rel="import" href="/components/iron-pages/iron-pages.html">
<link rel="import" href="/components/iron-resizable-behavior/iron-resizable-behavior.html">
<link rel="import" href="/components/iron-selector/iron-selectable.html">
<link rel="import" href="/components/iron-selector/iron-selection.html">
<link rel="import" href="/elements/fs-app-path/fs-app-path.html">
<link rel="import" href="/elements/tree-pwa/tree-behavior.html">
<link rel="import" href="/elements/tree-help/tree-help.html">
<link rel="import" href="/components/wc-i18n/wc-i18n.html">
<link rel="import" href="/components/fs-help-tray/fs-help-tray.html">
<link rel="import" href="/components/fs-styles/fs-styles.html">
<link rel="import" href="/components/fs-styles/dist/base.min.css">
<link rel="import" href="/components/fs-help-tray/fs-help-tray-styles.html">
<link rel="import" href="/components/fs-user-service/fs-user-service.html">
<link rel="import" href="/components/fs-cache/fs-cache.html">
<link rel="import" href="/components/fs-globals/fs-globals.html">
<link rel="import" href="/elements/tree-pedigree/tree-pedigree.html">
<link rel="import" href="/components/polymer/polymer.html">
<link rel="import" href="/components/wc-i18n/wc-i18n.html">
<link rel="import" href="/components/fs-cache/fs-cache.html">
<link rel="import" href="/components/fs-globals/fs-globals.html">
<link rel="import" href="/components/styles-wc/fs-icon-eol/fs-icon-eol.html">
<link rel="import" href="/elements/tree-pedigree/tree-pedigree-state.html">
<link rel="import" href="/elements/v8-redux/v8-redux.html">
<link rel="import" href="/components/polymer-redux/polymer-redux.html">
<link rel="import" href="/elements/tree-pedigree/pedigree-data-service.html">
<link rel="import" href="/components/fs-cache/fs-crypto.html">
<link rel="import" href="/elements/tree-pedigree/Pedigree.html">
<link rel="import" href="/elements/pedigree-preferences/pedigree-preferences.html">
<link rel="import" href="/components/oak-ajax-behavior/oak-ajax-behavior.html">
<link rel="import" href="/components/dialog-el/fs-dialog-eol.html">
<link rel="import" href="/components/fs-styles/fs-styles.html">
<link rel="import" href="/components/fs-styles/dist/base.min.css">
<link rel="import" href="/components/fs-user-service/fs-user-service.html">
<link rel="import" href="/components/iron-iconset-svg/iron-iconset-svg.html">
<link rel="import" href="/components/iron-meta/iron-meta.html">
<link rel="import" href="/components/styles-wc/fs-button-eol/fs-button-eol.html">
<link rel="import" href="/elements/pedigree-preferences/pedigree-preferences-state.html">
<link rel="import" href="/components/fs-metrics/fs-metrics.html">
<link rel="import" href="/elements/pedigree-couple-renderer/pedigree-couple-renderer.html">
<link rel="import" href="/components/fs-tree-person-renderer/fs-tree-person-renderer.html">
<link rel="import" href="/components/styles-wc/fs-person-eol/fs-person-eol.html">
<link rel="import" href="/components/oak-i18n-behavior/oak-i18n-behavior.html">
<link rel="import" href="/components/fs-person-data-service/fs-person-data-service.html">
<link rel="import" href="/components/fs-couple-renderer/fs-couple-renderer.html">
<link rel="import" href="/components/fs-indicators/fs-indicators.html">
<link rel="import" href="/components/fs-indicators/fs-indicators-service.html">
<link rel="import" href="/components/fs-indicators/fs-indicators-flyout/fs-indicators-flyout.html">
<link rel="import" href="/components/birch-inner-html/birch-inner-html.html">
<link rel="import" href="/components/dialog-el/fs-common-dialog-eol.html">
<link rel="import" href="/components/styles-wc/fs-alert-message-eol/fs-alert-message-eol.html">
<link rel="import" href="/components/fs-labelled-link/fs-labelled-link.html">
<link rel="import" href="/components/styles-wc/fs-badge-eol/fs-badge-eol.html">
<link rel="import" href="/components/fs-temple/fs-temple-reserve/fs-temple-reserve.html">
<link rel="import" href="/components/fs-temple/fs-temple-reserve-row/fs-temple-reserve-row.html">
<link rel="import" href="/components/fs-temple/fs-temple-ordinance-status/fs-temple-ordinance-status.html">
<link rel="import" href="/components/fs-temple/fs-temple-ordinance-status/ordinance-icon.html">
<link rel="import" href="/components/fs-permissions/fs-permissions.html">
<link rel="import" href="/components/fs-temple/fs-temple-request-ordinance-permission/fs-temple-request-ordinance-permission.html">
<link rel="import" href="/components/iron-pages/iron-pages.html">
<link rel="import" href="/components/iron-resizable-behavior/iron-resizable-behavior.html">
<link rel="import" href="/components/iron-selector/iron-selectable.html">
<link rel="import" href="/components/iron-selector/iron-selection.html">
<link rel="import" href="/components/fs-inner-html/fs-inner-html.html">
<link rel="import" href="/components/fs-temple/fs-temple-reserve/fs-temple-reserve-service.html">
<link rel="import" href="/components/fs-temple/fs-temple-legend/fs-temple-legend.html">
<link rel="import" href="/components/fs-temple/fs-temple-policy/fs-temple-policy.html">
<link rel="import" href="/components/fs-temple/fs-temple-icon/fs-temple-icon-service.html">
<link rel="import" href="/components/fs-temple/fs-temple-icon/fs-temple-icon.html">
<link rel="import" href="/elements/pedigree-couple-renderer/pedigree-couple-renderer-service.html">
<link rel="import" href="/elements/booklet-popover/booklet-popover.html">
<link rel="import" href="/components/app-route/app-route.html">
<link rel="import" href="/elements/tree-pwa/tree-behavior.html">
<link rel="import" href="/elements/tree-pedigree/save-state.html">
<link rel="import" href="/elements/fs-tree-navigation/fs-tree-navigation.html">
<link rel="import" href="/components/iron-media-query/iron-media-query.html">
<link rel="import" href="/elements/fs-app-path/fs-app-path.html">
<link rel="import" href="/components/iron-location/iron-location.html">
<link rel="import" href="/elements/history-list/history-list.html">
<link rel="import" href="/components/iron-list/iron-list.html">
<link rel="import" href="/components/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
<link rel="import" href="/components/iron-scroll-target-behavior/iron-scroll-target-behavior.html">
<link rel="import" href="/components/fs-add-person/fs-add-person.html">
<link rel="import" href="/components/resettable-properties-behavior/resettable-properties-behavior.html">
<link rel="import" href="/components/birch-standards-picker/birch-standards-picker.html">
<link rel="import" href="/components/birch-typeahead/birch-typeahead.html">
<link rel="import" href="/components/paper-listbox/paper-listbox.html">
<link rel="import" href="/components/iron-menu-behavior/iron-menu-behavior.html">
<link rel="import" href="/components/iron-selector/iron-multi-selectable.html">
<link rel="import" href="/components/paper-styles/default-theme.html">
<link rel="import" href="/components/paper-styles/color.html">
<link rel="import" href="/components/paper-item/paper-item.html">
<link rel="import" href="/components/iron-flex-layout/iron-flex-layout.html">
<link rel="import" href="/components/paper-item/paper-item-behavior.html">
<link rel="import" href="/components/iron-behaviors/iron-button-state.html">
<link rel="import" href="/components/iron-behaviors/iron-control-state.html">
<link rel="import" href="/components/paper-item/paper-item-shared-styles.html">
<link rel="import" href="/components/paper-styles/typography.html">
<link rel="import" href="/components/font-roboto/roboto.html">
<link rel="import" href="/components/paper-item/paper-item-body.html">
<link rel="import" href="/components/paper-item/paper-icon-item.html">
<link rel="import" href="/components/birch-typeahead/birch-typeahead.css">
<link rel="import" href="/components/paper-menu/paper-menu.html">
<link rel="import" href="/components/paper-menu/paper-menu-shared-styles.html">
<link rel="import" href="/components/birch-standards-picker/birch-standards-picker.css">
<link rel="import" href="/components/fs-add-person/fs-name-template/fs-name-template.html">
<link rel="import" href="/components/fs-cache/fs-cache-item.html">
<link rel="import" href="/components/fs-add-person/fs-transliteration-service/fs-transliteration-service.html">
<link rel="import" href="/components/fs-add-person/fs-search-results-couple/fs-search-results-couple.html">
<link rel="import" href="/components/fs-life-events/fs-life-events.html">
<link rel="import" href="/components/fs-add-person/fs-add-person-service/fs-add-person-service.html">
<link rel="import" href="/components/fs-add-person/fs-person-search-service/fs-person-search-service.html">
<link rel="import" href="/components/app-route/app-location.html">
<link rel="import" href="/components/iron-location/iron-query-params.html">
<link rel="import" href="/components/app-route/app-route-converter-behavior.html">
<link rel="import" href="/elements/first-run-start/first-run-start.html">
<my-app></my-app>
</body>
</html>
index.html

Front-load

Front-load Components
Interactive
16.1 => 14.5s
Async Javascript Loading


fs-cache.html
<link rel="import" href="../polymer/polymer.html">
<script src="../localforage/dist/localforage.nopromises.min.js"></script>
<script src="../localforage-sessionstoragewrapper/src/localforage-sessionstoragewrapper.js"></script>
<script src="../localForage-memoryStorageDriver/dist/localforage-memoryStorageDriver.js"></script>
<script src="./fs-cache.js"></script>
Resource Hints
Title Text
<link rel="dns-prefetch" href="https://fscdn.edge.com">
<link rel="preload" href="/script1.js" as="script">
<link rel="preload" href="/script2.js" as="script">
<link rel="import" href="/my-app.html">
Example
Front-load


Preload javascript
Interactive
Philippines 3G - 16.1 => 14.5 => 10.6s

Support
http://caniuse.com/#search=preload
Streaming
Example
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="dns-prefetch" href="origin.com">
<link rel="preload" href="script1.js" as="script">
<link rel="import" href="my-app.html">
<link rel="import" href="my-other.html">
</head>
<body>
<!-- person id received from xhr call on server -->
<my-app person-id="MMMM-MMM"></my-app>
</body>
</html>
Server makes xhr call to get data needed on page
1
2
3
Stream Pedigree Data
<script>
window.PEDIGREE_DATA = {data: 'data'};
</script>
<!-- person id received from xhr call on server -->
<my-app person-id="MMMM-MMM"></my-app>
</body>
</html>
Stream Pedigree Data
Interactive
16.1 => 14.5 => 10.6 => 8.7s
Support
All the browsers forever

http://knowyourmeme.com/
Justifications


Change of measurement
Cold Load
Navigate from homepage
Justifications
Interactive
16.1 => 14.5 => 10.6 => 8.7 => 6.2
Shipment
480 => 846KB
6.2 => 13.6s
On-demand/deferred
<script>
window.addEventListener('load', function(){
function importHrefs(hrefs){
hrefs.forEach(function(href){
Polymer.Base.importHref(href);
});
}
var links = [
"<%- resolvePath('/components/dialog-el/fs-common-dialog-eol.html') %>",
"<%- resolvePath('/elements/tree-help/tree-help.html') %>",
];
importHrefs(links);
});
</script>
Deferred Loading
(window load event)
_openIndicatorFlyoutEH: function(e){
e.stopPropagation();
this.loading = true;
this.importHref(flyoutHref, function(){
this.loading = false;
this._openIndicatorFlyout(evt);
}.bind(this));
}
On-demand Loading
When user clicks something

Deferred/On-demand
480 => 846 => 420KB
6.2 => 13.6 => 6.4s
Rollup
d3.js
75KB
d3-rollup.js
15KB
Future
H2 Server Push

https://speakerdeck.com/addyosmani/the-browser-hackers-guide-to-instant-loading
Waterfall

https://speakerdeck.com/addyosmani/the-browser-hackers-guide-to-instant-loading
Support

http://caniuse.com/#search=http2
Draw Back
Server doesn't know if asset is cached in browser, so it will always push.
Service Workers
to the rescue

Network Interceptor
Support

http://caniuse.com/#search=serviceworker
Lighthouse
https://developers.google.com/web/tools/lighthouse/
Ships in Chrome dev tools


Go and Do!

https://giphy.com
All of the fasts. Perf/Polymer
By Tyler Graf
All of the fasts. Perf/Polymer
- 979