Transcript
Page 1: Web Components at Scale, HTML5DevConf 2014-10-21
Page 2: Web Components at Scale, HTML5DevConf 2014-10-21

Chris Danford, @chrisdanfordPinterest Web Team

Web Components at Scale2014-10-20

Page 3: Web Components at Scale, HTML5DevConf 2014-10-21

Pinterest’s evaluation of Web ComponentsTopic Covered

• Migrating from our existing component framework• SEO impact• Page load perf• Polyfill gotchas• Browser compatibility

Page 4: Web Components at Scale, HTML5DevConf 2014-10-21

Background Learnings Conclusion TODO

Page 5: Web Components at Scale, HTML5DevConf 2014-10-21

2 years since major design decisions madeBackground

Page 6: Web Components at Scale, HTML5DevConf 2014-10-21

Pinterest has grownBackground

Then 7 engineers touching web

Now 70 engineers touching web

Page 7: Web Components at Scale, HTML5DevConf 2014-10-21

ArchitectureBackground

API

Android

Datalayer

iOSWeb

Graph ServiceSearch

Client Apps

Back-endServices

...

Page 8: Web Components at Scale, HTML5DevConf 2014-10-21

Web architectureBackground

Web server

Routing

Templates

Render a component tree

Behavior (event handlers)

Duplication

Page 9: Web Components at Scale, HTML5DevConf 2014-10-21

Existing component systemBackground

• Backbone View• Backbone Model• templates render to an HTML string, then innerHTML to

load• re-rendering a subtree throws away the old subtree

entirely

Page 10: Web Components at Scale, HTML5DevConf 2014-10-21

Style (.scss)

Structure (.html)

Behavior (.js)

Page 11: Web Components at Scale, HTML5DevConf 2014-10-21

from a template

from JS

Page 12: Web Components at Scale, HTML5DevConf 2014-10-21

Web Components score cardBackground

• Migrate gradually• Compatible with existing tooling• Content Security Policy• Page load performance (too much)• Don’t hurt SEO• Encapsulation of DOM and styles• Don’t cut off too many browser versions

Page 13: Web Components at Scale, HTML5DevConf 2014-10-21

Background Learnings Conclusion TODO

Page 14: Web Components at Scale, HTML5DevConf 2014-10-21

Custom Elements lifecycle functionsMigrate Gradually

Pinterest onCreated

onAddedToDomonContentReady

onRemovedFromDom

Custom Elements createdCallbackattachedCallback

—detachedCallback

Polymer created

attacheddomReadydetached

Page 15: Web Components at Scale, HTML5DevConf 2014-10-21

Each component renders itself in attachedCallbackQuick prototype

Page 16: Web Components at Scale, HTML5DevConf 2014-10-21

Migrate Gradually

Page 17: Web Components at Scale, HTML5DevConf 2014-10-21

Can work with existing toolingPreserve Existing Tools

• SASS• ESLint• Closure Compiler• Syntax-highlighting editors

Page 18: Web Components at Scale, HTML5DevConf 2014-10-21

External scripts and stylesheets are no problemPreserve Existing Tools

• Polymer docs: Separating scripts from markup

Page 19: Web Components at Scale, HTML5DevConf 2014-10-21

Works with Existing Tooling

Page 20: Web Components at Scale, HTML5DevConf 2014-10-21

Polyfill problemsDon’t break Content Security Policy

• The HTML Imports polyfill loads imports using XMLHttpRequest then evals script

Page 21: Web Components at Scale, HTML5DevConf 2014-10-21

Content Security PolicyRequirements

• If you keep your styles and scripts external, there’s no action needed.

• If you write inline styles or inline scripts, use the “csp” flag and Vulcanize will extract them to separate files.

grunt.initConfig({ vulcanize: { options: { csp: true, ... }, files: { 'out.html': 'comps/**.html' }, }, });

Page 22: Web Components at Scale, HTML5DevConf 2014-10-21

Content Security Policy

Page 23: Web Components at Scale, HTML5DevConf 2014-10-21

Server-side Rendering

• No story at all for Web Components/Polymer• If we can get away with it, we’d rather eliminate the Python

code path for templates/rendering• What is the impact on

• Page load times?• SEO?

Page 24: Web Components at Scale, HTML5DevConf 2014-10-21

Nice to havePage Load Performance

• Not critical, but don’t want to regress more than 10-20%.• The median user has < 2 page refreshes per visit. Almost

every interaction is a pushState.• Indirectly affects SEO (speed is a factor in scoring).

Page 25: Web Components at Scale, HTML5DevConf 2014-10-21

ExperimentPage Load Performance

• Control: Render the initial content sever-side in Python and send it as HTML in the page load

• Treatment: Serve meta tags and correct HTTP response codes, but render all of the visible content in JS.

• Measure using Web Page Test’s SpeedIndex - a measure of how early the final pixels are painted. Lower is better.

• An explanation of SpeedIndex

Page 26: Web Components at Scale, HTML5DevConf 2014-10-21

Page Load Performance

Server-rendered JS-rendered Difference

First View 5073 5236 3%

Repeat View 2571 3114 20%

SpeedIndex, San Jose, DSL, Chrome

Page 27: Web Components at Scale, HTML5DevConf 2014-10-21

Page Load Performance

A pleasant surprise!

Page 28: Web Components at Scale, HTML5DevConf 2014-10-21

Important to not regressSEO

• Web doesn’t have the most active users of all the Pinterest client apps.

• Web is the largest source of acquisition.

Page 29: Web Components at Scale, HTML5DevConf 2014-10-21

Organic search traffic by sourceSEO

In practice, we are targeting Google crawler.

Page 30: Web Components at Scale, HTML5DevConf 2014-10-21

Does Google’s crawler understand JS?SEO

Historically: “No”

May 23, 2014:“we decided to try to (better) understand pages by executing JavaScript”

-Google

Page 31: Web Components at Scale, HTML5DevConf 2014-10-21

A/B test JS-rendered pageSEO

• 10% of “Board” pages will render all of their components client-side

• Takes Google roughly 1 week to re-index all content and for us to see the true impact

Page 32: Web Components at Scale, HTML5DevConf 2014-10-21

SEO

5% decline in traffic vs. control group after only 1.5 days

Page 33: Web Components at Scale, HTML5DevConf 2014-10-21

“Fetch as Google”SEO

• A tool in Google Webmaster Tools that shows what the crawler sees.

Rendering pages with Fetch as Google post

Page 34: Web Components at Scale, HTML5DevConf 2014-10-21

• Crawler is seeing some client-rendered components. (yay!)

• Content area of the page was blank. (boo)

• An XHRs was needed to render the content, but the crawler blocked it. Eliminate the need for the XHR.

Page 35: Web Components at Scale, HTML5DevConf 2014-10-21

Next experimentSEO

• Inline the data into the page to eliminate the XHR.

Page 36: Web Components at Scale, HTML5DevConf 2014-10-21

SEO

But I’m optimistic!

Page 37: Web Components at Scale, HTML5DevConf 2014-10-21

Shadow DOMDOM Encapsulation

It’s a heroic (crazy?) effort to make this work as a polyfill.Overrides• 20 methods on HTMLElement• 44 methods on Document• 69 element contructors

Page 38: Web Components at Scale, HTML5DevConf 2014-10-21

Shadow DOM, continuedDOM Encapsulation

Quirks• document, window, document.body, document.head

can’t be wrapped by the polyfill, and you need to manually wrap:• wrap(document.body)

• Console shortcuts to grab elements return the unwrapped element and need to be wrapped.• wrap($0)

Page 39: Web Components at Scale, HTML5DevConf 2014-10-21

Shadow CSSStyle Encapsulation

A style shimmer: re-writes CSS text with a bunch of regexes

Page 40: Web Components at Scale, HTML5DevConf 2014-10-21

Shadow CSS - what worksStyle Encapsulation

• Replace :host with element selector• Add upper-bound encapsulation by prepending element

selector

Page 41: Web Components at Scale, HTML5DevConf 2014-10-21

Easy with a CSS preprocessor tooStyle Encapsulation

Page 42: Web Components at Scale, HTML5DevConf 2014-10-21

Shadow CSS - limitationsStyle Encapsulation

“For browsers that lack native support, Polymer’s polyfills attempt to shim some of the scoping behavior.”

-Polyfill Details

Page 43: Web Components at Scale, HTML5DevConf 2014-10-21

Chrome 38 (native) Firefox 32 (polyfill)

Page 44: Web Components at Scale, HTML5DevConf 2014-10-21

Shadow CSS - limitations galoreStyle Encapsulation

Can’t polyfill lower-bound encapsulation• Platform.ShadowCSS.strictStyling = true;• Requires that you add custom element’s name as an attribute

on all DOM nodes in the shadowRoot e.g. <span x-foo> • Nobody is going to do that without a build step, so why bother

polyfilling this at all?

Page 45: Web Components at Scale, HTML5DevConf 2014-10-21
Page 46: Web Components at Scale, HTML5DevConf 2014-10-21

Unless you like testing in different browsers

• Force the Shadow DOM polyfill to be enabled.

Page 47: Web Components at Scale, HTML5DevConf 2014-10-21

Shadow DOMShadow CSS

Page 48: Web Components at Scale, HTML5DevConf 2014-10-21

Polymer-stated supportBrowser Compatibility

IE < 10 is hopelessSafari < 6 is hopeless

https://www.polymer-project.org/resources/compatibility.html

Page 49: Web Components at Scale, HTML5DevConf 2014-10-21

Pinterest browsers by visitorBrowser Compatibility

5.05%+ of visitors incompatible

Page 50: Web Components at Scale, HTML5DevConf 2014-10-21

Pinterest browsers by visitorBrowser Compatibility

5.05%+ of visitors incompatible9.25%+

Page 51: Web Components at Scale, HTML5DevConf 2014-10-21

AnecdotesBrowser Compatibility

• Android Browser 4.1 and 4.3 not working with any of the demos

Page 52: Web Components at Scale, HTML5DevConf 2014-10-21

AnecdotesBrowser Compatibility

• Chrome 37 crashes frequently with dev tools open making tweaks to the Polymer tutorial

• iOS8 was broken well after the GM shipped and didn’t work until just before public launch

Page 53: Web Components at Scale, HTML5DevConf 2014-10-21

Anecdotes - IE10Browser Compat

• the renderer process locks up on an unpatched IE10 (e.g. modern.ie image that has updates turned off)

Page 54: Web Components at Scale, HTML5DevConf 2014-10-21

Anecdotes - IE10Browser Compat

10.0.10 10.0.20

Page 55: Web Components at Scale, HTML5DevConf 2014-10-21

Anecdotes - IE10Browser Compat

• Can’t tell how many users this might impact because build # isn’t in the UA string.

Page 56: Web Components at Scale, HTML5DevConf 2014-10-21

Browser Compatibility

Page 57: Web Components at Scale, HTML5DevConf 2014-10-21

Background Learnings Conclusion TODO

Page 58: Web Components at Scale, HTML5DevConf 2014-10-21

Conclusion

Migrate GraduallyWorks with Existing Tooling

Content Security PolicyPage Load Performance

SEOShadow DOMShadow CSS

Browser Compatibility

Page 59: Web Components at Scale, HTML5DevConf 2014-10-21

Polymer architecture

Polymer.js

• TemplateBinding• syntactic sugar

(polymer-element tag, on-*event* attribute binding)

• tooling (Vulcanize, Polymer Designer)

core-elements

paper-elements

Platform.js

“Prollyfills”• ShadowDOM• HTMLImports• Custom Elements• MutationObserver• Object.observe

• menus• drawers• panels• animation

framework

Page 60: Web Components at Scale, HTML5DevConf 2014-10-21

Background Learnings Conclusion TODO

Page 61: Web Components at Scale, HTML5DevConf 2014-10-21

Next Steps

• SEO• eliminate the XHR, reset the experiment

• Browser compatibility• try to measure impact on IE10• Pieces of platform.js that work on more browsers (Custom

Elements?)• Finish evaluating other framework options

Page 62: Web Components at Scale, HTML5DevConf 2014-10-21
Page 63: Web Components at Scale, HTML5DevConf 2014-10-21

engineering.pinterest.com@chrisdanford

Page 64: Web Components at Scale, HTML5DevConf 2014-10-21

Top Related