Michael North "The Road to Native Web Components"

51
Mike North CTO Levanto Financial The Road to Native Web Components

Transcript of Michael North "The Road to Native Web Components"

Page 1: Michael North "The Road to Native Web Components"

Mike NorthCTO Levanto Financial

The Road to Native Web Components

Page 2: Michael North "The Road to Native Web Components"

INTRODUCTION

WHO’S THIS GUY?

▸ CTO Levanto Financial

▸ frontendmasters.com instructor

▸ Product Guy

▸ I do a lot of JavaScript OSS stuff

▸ I work with Ember & React a lot

Page 3: Michael North "The Road to Native Web Components"

DOCUMENT VIEWER

DOCUMENT

Page 4: Michael North "The Road to Native Web Components"

INTRO

DO YOU USE WEB COMPONENTS? (YES)

Page 5: Michael North "The Road to Native Web Components"
Page 6: Michael North "The Road to Native Web Components"
Page 7: Michael North "The Road to Native Web Components"

INTRO

THE W3C WEB COMPONENT SPEC

HTML IMPORTS

HTML TEMPLATES

CUSTOM ELEMENTS

SHADOW DOM

Page 8: Michael North "The Road to Native Web Components"

INTRO

THE W3C WEB COMPONENT SPEC

HTML IMPORTS

▸ require() for HTML

▸ onload, onerror events

▸ can bring in css/html/js

▸ closure-like js characteristics

Page 9: Michael North "The Road to Native Web Components"

INTRO

THE W3C WEB COMPONENT SPEC

CUSTOM ELEMENTS

▸ Custom HTML vocab

▸ Life-cycle

▸ Extensibility

▸ Interoperability (we hope?)

Page 10: Michael North "The Road to Native Web Components"

INTRO

THE W3C WEB COMPONENT SPEC

HTML TEMPLATES

▸ Inert HTML in the DOM

▸ Defer loading / rendering

▸ Think: handlebars/jade/etc…

Page 11: Michael North "The Road to Native Web Components"

INTRO

THE W3C WEB COMPONENT SPEC

SHADOW DOM

▸ CSS Encapsulation

▸ DOM encapsulation

▸ Each component has own subtree w/in parent page

Page 12: Michael North "The Road to Native Web Components"

INTRO

THE W3C WEB COMPONENT SPEC

HTML IMPORTS

HTML TEMPLATES

CUSTOM ELEMENTS

SHADOW DOM

Page 13: Michael North "The Road to Native Web Components"

HTML TEMPLATES

Page 14: Michael North "The Road to Native Web Components"

<!DOCTYPE html> <html> <head></head> <body>

<template id="something"> <div class="frame"> <h3 class="title">I am a title</h3> <p class="body">I am the body</p> </div> </template> </body> </html>

Page 15: Michael North "The Road to Native Web Components"

<template id="something"> <div class="frame"> <h3 class="title">I am a title</h3> <p class="body">I am the body</p> </div> </template>

Page 16: Michael North "The Road to Native Web Components"

<template id="something"> <!-- Some style --> <style type="text/css"> .title { font-size: 24px; } </style> <!-- Some behavior --> <script type="text/javascript"> </script> <!-- Some structure and content --> <div class="frame"> <h3 class="title">I am a title</h3> <p class="body">I am the body</p> </div> </template>

Page 17: Michael North "The Road to Native Web Components"

// Grab the template var tmpl = document.querySelector(‘#something');

Add the cloned document fragment to the DOM document.body.appendChild( // Clone the template's document fragment document.importNode(tmpl.content, true) );

Page 18: Michael North "The Road to Native Web Components"

// Grab the template var tmpl = document.querySelector(‘#something');

Add the cloned document fragment to the DOM document.body.appendChild( // Clone the template's document fragment document.importNode(tmpl.content, true) );

Page 19: Michael North "The Road to Native Web Components"

http://codepen.io/TrueNorth/pen/xbyVgL?editors=101

Page 20: Michael North "The Road to Native Web Components"

HOW DO FRAMEWORKS HANDLE THIS?

Page 21: Michael North "The Road to Native Web Components"

define('examples/templates/index', ['exports'], function (exports) {

'use strict';

exports['default'] = Ember.HTMLBars.template((function() { return { ... buildFragment: function buildFragment(dom) { var el0 = dom.createDocumentFragment(); var el1 = dom.createTextNode("Hello, "); dom.appendChild(el0, el1); var el1 = dom.createElement("strong"); var el2 = dom.createComment(""); dom.appendChild(el1, el2); var el2 = dom.createTextNode(" "); dom.appendChild(el1, el2); var el2 = dom.createComment(""); dom.appendChild(el1, el2); dom.appendChild(el0, el1); var el1 = dom.createTextNode("!"); dom.appendChild(el0, el1); return el0; }, buildRenderNodes: function buildRenderNodes(dom, fragment, contextualElement) { var element0 = dom.childAt(fragment, [1]); var morphs = new Array(2); morphs[0] = dom.createMorphAt(element0,0,0); morphs[1] = dom.createMorphAt(element0,2,2); return morphs; }, statements: [ ["content","firstName",["loc",[null,[1,15],[1,28]]]], ["content","lastName",["loc",[null,[1,29],[1,41]]]] ],

... }; }()));});

Page 22: Michael North "The Road to Native Web Components"

LAZY LOADINGLazy engines, JIT template compiler

Webpack chunking

Webpack chunking

Page 23: Michael North "The Road to Native Web Components"

SHADOW DOM

Page 24: Michael North "The Road to Native Web Components"

APPLICATION DOM

COMPONENT

SHADOW DOM

Page 25: Michael North "The Road to Native Web Components"

SHADOW DOM

ENCAPSULATION http://codepen.io/mike-north/pen/OPBNmq?editors=101

Page 26: Michael North "The Road to Native Web Components"

SHADOW DOM

CSS ENCAPSULATION

▸ CSS rules do not usually pierce shadow roots

▸ CSS defined inside the shadow root only affects that DOM

▸ :host pseudo-selector for component boundary

▸ ::shadow penetrates shadow roots

▸ /deep/ is deprecated

// Inside shadow root :host { border: 1px solid red; } :host(.hover) { border: 1px solid blue; }

// Outside shadow root #my-thing::shadow p { color: green; }

Page 27: Michael North "The Road to Native Web Components"

HOW DO FRAMEWORKS HANDLE THIS?

Page 28: Michael North "The Road to Native Web Components"

CSS ENCAPSULATIONember-css-modules ember-component-css

“component styles”

react-css-modules

Page 29: Michael North "The Road to Native Web Components"
Page 30: Michael North "The Road to Native Web Components"

SHADOW DOM

CONTENT PROJECTION

Page 31: Michael North "The Road to Native Web Components"

<textarea name="comment" id="" cols="30" > This is the content of my textarea </textarea>

SHADOW DOM

CONTENT PROJECTION

Page 32: Michael North "The Road to Native Web Components"

http://codepen.io/mike-north/pen/emPZMv?editors=1000

Page 33: Michael North "The Road to Native Web Components"

CONTENT PROJECTION{{yield}}

2.x <ng-content>, 1.x ng-transclude

this.props.children

Page 34: Michael North "The Road to Native Web Components"

HTML IMPORTS

Page 35: Michael North "The Road to Native Web Components"

<link rel="import" href="myfile.html" />

Page 36: Michael North "The Road to Native Web Components"

<link rel="import" href="myfile.html" />

// Get document fragment of an import var content = document .querySelector('link[rel="import"]') .import;

Page 37: Michael North "The Road to Native Web Components"

<link rel="import" href="myfile.html" />

// Get document fragment of an import var content = document .querySelector('link[rel="import"]') .import;

// From a <script> included with the import, // access imported DOM var $abc = document .currentScript .ownerDocument .querySelector('.abc');

Page 38: Michael North "The Road to Native Web Components"

HOW DO FRAMEWORKS HANDLE THIS?

Page 39: Michael North "The Road to Native Web Components"

IMPORTING COMPONENTS

import MyComponent from 'my-component';

Page 40: Michael North "The Road to Native Web Components"

CUSTOM ELEMENTS

Page 41: Michael North "The Road to Native Web Components"

CUSTOM ELEMENTS

WHY IS THIS IMPORTANT

▸ Composable building blocks

▸ Life-cycle

▸ Extensibility

▸ Alignment of HTML with mental model of your UI

Page 42: Michael North "The Road to Native Web Components"

CUSTOM ELEMENTS

REGISTERING

// Extend a DOM element prototype var MegaButtonProto = Object.create(HTMLButtonElement.prototype);

Page 43: Michael North "The Road to Native Web Components"

CUSTOM ELEMENTS

REGISTERING

// Extend a DOM element prototype var MegaButtonProto = Object.create(HTMLButtonElement.prototype);

// Register your new element type var MegaButton = document.registerElement("mega-button", { prototype: MegaButtonProto, extends: "button" });

Page 44: Michael North "The Road to Native Web Components"

CUSTOM ELEMENTS

ADDING A TEMPLATE// Template var infoBoxTemplate = document.querySelector('#info-pane-template');

// Extend a DOM element var InfoBoxProto = Object.create(HTMLElement.prototype, { createdCallback: { value: function() { // Create the shadow root this.createShadowRoot().appendChild( // Add the template to the shadow root document.importNode(infoBoxTemplate.content, true) ); } } });

Page 45: Michael North "The Road to Native Web Components"

CUSTOM ELEMENTS

ADDING A TEMPLATE// Template var infoBoxTemplate = document.querySelector('#info-pane-template');

// Extend a DOM element var InfoBoxProto = Object.create(HTMLElement.prototype, { createdCallback: { value: function() { // Create the shadow root this.createShadowRoot().appendChild( // Add the template to the shadow root document.importNode(infoBoxTemplate.content, true) ); } } });

Page 46: Michael North "The Road to Native Web Components"

// Template var infoBoxTemplate = document.querySelector('#info-pane-template');

// Extend a DOM element var InfoBoxProto = Object.create(HTMLElement.prototype, { createdCallback: { value: function() { // Create the shadow root this.createShadowRoot().appendChild( // Add the template to the shadow root document.importNode(infoBoxTemplate.content, true) ); } } });

CUSTOM ELEMENTS

ADDING A TEMPLATE

Page 47: Michael North "The Road to Native Web Components"

HOW DO FRAMEWORKS HANDLE THIS?

Page 48: Michael North "The Road to Native Web Components"

CUSTOM ELEMENTSEmber.Component

@Component

React.Component

Page 49: Michael North "The Road to Native Web Components"

DEMO

Page 50: Michael North "The Road to Native Web Components"

DEMO•Starting Point: http://codepen.io/TrueNorth/pen/PwdLrj •Componentized: http://codepen.io/TrueNorth/pen/xbyqME •HTML Importified: http://codepen.io/TrueNorth/pen/ogawLm