2016 stop writing javascript frameworks by joe gregorio

151
Stop Writing Javascript Frameworks Joe Gregorio @bitworking bit.ly/zf-preso-2

Upload: david-zapateria

Post on 12-Apr-2017

56 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: 2016 stop writing javascript frameworks by Joe Gregorio

Stop Writing Javascript Frameworks

Joe Gregorio@bitworking

bit.ly/zf-preso-2

Page 2: 2016 stop writing javascript frameworks by Joe Gregorio

● I am employed by Google

● This talk does not represent the opinion of Google

Caveats

Page 3: 2016 stop writing javascript frameworks by Joe Gregorio

● Code is for exposition purposes only.

Caveats

Page 4: 2016 stop writing javascript frameworks by Joe Gregorio

● Those expecting magic and/or cleverness.

Apologies in Advance

Page 5: 2016 stop writing javascript frameworks by Joe Gregorio

● Open Source https://skia.org● 2D Graphics Library

○ CPU○ GPU○ PDF

About Skia

Page 6: 2016 stop writing javascript frameworks by Joe Gregorio

● Chrome● Android● Firefox● Flutter.io● Sublime Text 3● ...

About Skia

Page 7: 2016 stop writing javascript frameworks by Joe Gregorio

● Hidden Gems○ PathOps

https://skia.org/dev/present/pathops ○ SkNx https://skia.org/dev/contrib/simd

About Skia

Page 8: 2016 stop writing javascript frameworks by Joe Gregorio

● Infrastructure○ Run the Tests○ Tools for Analysis

■ 500,000 Images/Commit■ 260,000 Perf Metrics/Commit

About Me

Page 9: 2016 stop writing javascript frameworks by Joe Gregorio

● Go● Polymer● Google Compute Engine● Open Source

○ https://skia.googlesource.com/buildbot/

About Skia Infra

Page 10: 2016 stop writing javascript frameworks by Joe Gregorio
Page 11: 2016 stop writing javascript frameworks by Joe Gregorio
Page 12: 2016 stop writing javascript frameworks by Joe Gregorio
Page 13: 2016 stop writing javascript frameworks by Joe Gregorio
Page 14: 2016 stop writing javascript frameworks by Joe Gregorio
Page 15: 2016 stop writing javascript frameworks by Joe Gregorio

● Build fast● Iterate quickly● Maintain robustly● Do things at scale

Context

Page 16: 2016 stop writing javascript frameworks by Joe Gregorio

Stop Writing Javascript Frameworks

http://bitworking.org/news/2014/05/zero_framework_manifesto

Page 17: 2016 stop writing javascript frameworks by Joe Gregorio

using hyperbole

https://xkcd.com/386/

Slightly Hyperbolic Title

Page 18: 2016 stop writing javascript frameworks by Joe Gregorio

Things I didn't say

● Stop innovating.

● Stop using Javascript libraries.

● Stop using tools.

● I have all the answers.

Page 19: 2016 stop writing javascript frameworks by Joe Gregorio

Alternate Accurate Titles

● Stop Using Javascript Frameworks

● Start writing reusable orthogonally

composable units of HTML+CSS+JS

Page 20: 2016 stop writing javascript frameworks by Joe Gregorio

Stop Writing Using Javascript Frameworks

Joe Gregorio@bitworking

Page 21: 2016 stop writing javascript frameworks by Joe Gregorio

What do I mean by "framework"?

Page 22: 2016 stop writing javascript frameworks by Joe Gregorio

gist -> library -> framework

Page 23: 2016 stop writing javascript frameworks by Joe Gregorio

gist -> library -> framework

Trouble starts here

Page 24: 2016 stop writing javascript frameworks by Joe Gregorio

● HTML

● CSS

● JS

Page 25: 2016 stop writing javascript frameworks by Joe Gregorio
Page 26: 2016 stop writing javascript frameworks by Joe Gregorio

● HTML

● CSS

● JS

Page 27: 2016 stop writing javascript frameworks by Joe Gregorio

GWT

Page 28: 2016 stop writing javascript frameworks by Joe Gregorio

● HTML

● CSS

● JS

Page 29: 2016 stop writing javascript frameworks by Joe Gregorio

There was a time for frameworks

Page 30: 2016 stop writing javascript frameworks by Joe Gregorio

Remember the IE box model?

Page 32: 2016 stop writing javascript frameworks by Joe Gregorio

Remember the IE event model?

Page 34: 2016 stop writing javascript frameworks by Joe Gregorio

Remember the Netscape layer tag?

Page 35: 2016 stop writing javascript frameworks by Joe Gregorio

<LAYER ID=layer1 TOP=20pt LEFT=5pt BGCOLOR="#CC00EE" WIDTH=200> <H1>Layer 1</H1> <P>Lots of content for this layer.</P> <IMG SRC=violets.jpg align=right> <P>Content for layer 1.</P> <P>More Content for layer 1.</P></LAYER>

http://web.archive.org/web/20040929103224/http://developer.netscape.com/docs/manuals/communicator/dynhtml/index.htm

Page 36: 2016 stop writing javascript frameworks by Joe Gregorio

There was no consistent model for interacting with the browser.

Page 37: 2016 stop writing javascript frameworks by Joe Gregorio

The situation has improved

Page 38: 2016 stop writing javascript frameworks by Joe Gregorio

http://caniuse.com/#feat=svg

Page 39: 2016 stop writing javascript frameworks by Joe Gregorio

So that weakens one reason to use a framework.

Page 40: 2016 stop writing javascript frameworks by Joe Gregorio

Polyfills

The "import __future__" for the web.

Page 41: 2016 stop writing javascript frameworks by Joe Gregorio

Framework

Polyfills

Fill in the potholes.

Page 42: 2016 stop writing javascript frameworks by Joe Gregorio

But what about all the other benefits a framework brings?

Page 43: 2016 stop writing javascript frameworks by Joe Gregorio

Abstractions are Leaky

Page 44: 2016 stop writing javascript frameworks by Joe Gregorio
Page 45: 2016 stop writing javascript frameworks by Joe Gregorio

Abstractions are Abstract

Page 47: 2016 stop writing javascript frameworks by Joe Gregorio

Reuse

Page 48: 2016 stop writing javascript frameworks by Joe Gregorio

Busy porting my Dojo widgets to Backbone.

Page 49: 2016 stop writing javascript frameworks by Joe Gregorio

Angular 1.0 -> 2.0

Page 50: 2016 stop writing javascript frameworks by Joe Gregorio
Page 51: 2016 stop writing javascript frameworks by Joe Gregorio

Framework

Polyfills

Fill in the potholes.

Code organization

?

Page 52: 2016 stop writing javascript frameworks by Joe Gregorio

Framework

Polyfills Web Components

Fill in the potholes.

Code organization

Page 53: 2016 stop writing javascript frameworks by Joe Gregorio

Web Components

● HTML Templates● HTML Imports● Custom Elements● Shadow DOM

Page 54: 2016 stop writing javascript frameworks by Joe Gregorio

Web Components

● HTML Templates● HTML Imports● Custom Elements● Shadow DOM

Page 55: 2016 stop writing javascript frameworks by Joe Gregorio

HTML Templates

● Now part of HTML spec

Page 56: 2016 stop writing javascript frameworks by Joe Gregorio

HTML Templates

Page 57: 2016 stop writing javascript frameworks by Joe Gregorio

HTML Templates

● <template>...</template>● Content is parsed by browser.● Content is not rendered (invisible to user).● Content is hidden (invisible to

querySelector).● Content is inert. (JS doesn't run)

Page 58: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <div>Hello World!</div></template>

<script> var node = document.importNode( document.querySelector('#t').content, true); document.body.appendChild(node);</script>

Page 59: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <div>Hello World!</div></template>

<script> var node = document.importNode( document.querySelector('#t').content, true); document.body.appendChild(node);</script>

Page 60: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <div>Hello World!</div></template>

<script> var node = document.importNode( document.querySelector('#t').content, true); document.body.appendChild(node);</script>

Page 61: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <div>Hello World!</div></template>

<script> var node = document.importNode( document.querySelector('#t').content, true); document.body.appendChild(node);</script>

Page 62: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <div>Hello World!</div></template>

<script> var node = document.importNode( document.querySelector('#t').content, true); document.body.appendChild(node);</script>

bit.ly/zf-template

Page 63: 2016 stop writing javascript frameworks by Joe Gregorio

HTML Imports● <link rel="import" href="">

● Oddly slightly contentious.

● Brilliant for code organization, keep HTML, CSS, and JS together in one file.

Page 64: 2016 stop writing javascript frameworks by Joe Gregorio

HTML Imports● Are de-dup'd

● Can contain anything an HTML file can contain (HTML, CSS, JS)

● Scripts are executed in the context of the window that imported them

Page 65: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <div> Hello World! </div></template>

<script> (function() { var doc = document.currentScript.ownerDocument; var node = document.importNode( doc.querySelector( '#t').content, true); document.body.appendChild(node); })();</script>

import.html

Page 66: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <div> Hello World! </div></template>

<script> (function() { var doc = document.currentScript.ownerDocument; var node = document.importNode( doc.querySelector('#t').content, true); document.body.appendChild(node); })();</script>

import.html

Page 67: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <div> Hello World! </div></template>

<script> (function() { var doc = document.currentScript.ownerDocument; var node = document.importNode( doc.querySelector('#t').content, true); document.body.appendChild(node); })();</script>

import.html

Page 68: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <div> Hello World! </div></template>

<script> (function() { var doc = document.currentScript.ownerDocument; var node = document.importNode( doc.querySelector('#t').content, true); document.body.appendChild(node); })();</script>

import.html

Page 69: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <div> Hello World! </div></template>

<script> (function() { var doc = document.currentScript.ownerDocument; var node = document.importNode( doc.querySelector('#t').content, true); document.body.appendChild(node); })();</script>

import.html

Page 70: 2016 stop writing javascript frameworks by Joe Gregorio

<html> <head> <script src="webcomponents.js"></script> <link rel="import" href="import.html"> </head> <body> </body></html>

bit.ly/zf-html-imports-tmpl

index.html

Page 71: 2016 stop writing javascript frameworks by Joe Gregorio

<html> <head> <script src="webcomponents.js"></script> <link rel="import" href="import.html"> </head> <body> </body></html>

bit.ly/zf-html-imports-tmpl

index.html

http://webcomponents.org

Page 72: 2016 stop writing javascript frameworks by Joe Gregorio

<html> <head> <script src="webcomponents-lite.js"></script> <link rel="import" href="import.html"> </head> <body> </body></html>

bit.ly/zf-html-imports-tmpl

index.html

Page 73: 2016 stop writing javascript frameworks by Joe Gregorio

<html> <head> <script src="webcomponents.js"></script> <link rel="import" href="import.html"> </head> <body> </body></html>

bit.ly/zf-html-imports-tmpl

index.html

Page 74: 2016 stop writing javascript frameworks by Joe Gregorio

Context = function() { this.doc = (document.currentScript||document._currentScript).ownerDocument;};

Context.prototype. import = function(id) { return document.importNode(this.doc.querySelector( '#'+id).content, true);};

util.js

Page 75: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <div class=greeting> Hello World! </div></template>

<script> (function() { var ctx = new Context(); document.body.appendChild(ctx. import('t')); })();</script>

bit.ly/zf-import-context

import.html

Page 76: 2016 stop writing javascript frameworks by Joe Gregorio

Custom Elements

● Oddly uncontentious

● Only talking about creating new elements, not subclassing existing elements.

Page 77: 2016 stop writing javascript frameworks by Joe Gregorio

var proto = Object.create(HTMLElement.prototype);

proto.createdCallback = function() { this.textContent = 'Hello World!';};

proto.addMoreText = function(s) { this.textContent = this.textContent + s;};

document.registerElement('hello-element', { prototype: proto});

Page 78: 2016 stop writing javascript frameworks by Joe Gregorio

var proto = Object.create(HTMLElement.prototype);

proto.createdCallback = function() { this.textContent = 'Hello World!';};

proto.addMoreText = function(s) { this.textContent = this.textContent + s;};

document.registerElement('hello-element', { prototype: proto});

Page 79: 2016 stop writing javascript frameworks by Joe Gregorio

var proto = Object.create(HTMLElement.prototype);

proto.createdCallback = function() { this.textContent = 'Hello World!';};

proto.addMoreText = function(s) { this.textContent = this.textContent + s;};

document.registerElement('hello-element', { prototype: proto});

Page 80: 2016 stop writing javascript frameworks by Joe Gregorio

Custom Element Lifecycle Callbacks

createdCallback

attachedCallback

detachedCallback

attributeChangedCallback

Page 81: 2016 stop writing javascript frameworks by Joe Gregorio

var proto = Object.create(HTMLElement.prototype);

proto.createdCallback = function() { this.textContent = 'Hello World!';};

proto.addMoreText = function(s) { this.textContent = this.textContent + s;};

document.registerElement('hello-element', { prototype: proto});

Page 82: 2016 stop writing javascript frameworks by Joe Gregorio

var proto = Object.create(HTMLElement.prototype);

proto.createdCallback = function() { this.textContent = 'Hello World!';};

proto.addMoreText = function(s) { this.textContent = this.textContent + s;};

document.registerElement('hello-element', { prototype: proto});

Page 83: 2016 stop writing javascript frameworks by Joe Gregorio

<html><body>

<hello-element></hello-element></body></html>

bit.ly/zf-custom-element

Page 84: 2016 stop writing javascript frameworks by Joe Gregorio

Context = function() { this.doc = (document.currentScript||document._currentScript).ownerDocument;};

Context.prototype. import = function(id) { return document.importNode(this.doc.querySelector( '#'+id).content, true);};

function newElement(name, proto) { var ep = Object.create(HTMLElement.prototype); Object.keys(proto).forEach( function(key) { ep[key] = proto[key]; }); document.registerElement(name, {prototype : ep});}

util.js

Page 85: 2016 stop writing javascript frameworks by Joe Gregorio

Context = function() { this.doc = (document.currentScript||document._currentScript).ownerDocument;};

Context.prototype. import = function(id) { return document.importNode( this.doc.querySelector('#'+id).content, true);};

function newElement(name, proto) { var ep = Object.create(HTMLElement.prototype); Object.keys(proto).forEach(function(key) { ep[key] = proto[key]; }); document.registerElement(name, {prototype: ep});}

util.js

Page 86: 2016 stop writing javascript frameworks by Joe Gregorio

newElement('hello-element', {

createdCallback: function() { this.textContent = 'Hello World!'; },

addMoreText: function(s) { this.textContent = this.textContent + s; },});

bit.ly/zf-newelement

Page 87: 2016 stop writing javascript frameworks by Joe Gregorio

Putting it all together

A motivating example

Page 88: 2016 stop writing javascript frameworks by Joe Gregorio
Page 89: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <button>Hide</button></template>

<script> (function() { var ctx = new Context();

newElement('toggle-next', { createdCallback: function() { this.appendChild(ctx.import('t')); this.button = this.querySelector('button'); this.button.addEventListener('click', this._buttonClick.bind(this)); },

_buttonClick: function() { var current = this.nextElementSibling.style.visibility; if (current == 'collapse') { this.nextElementSibling.style.visibility = 'visible'; this.button.innerText = 'Hide'; } else { this.nextElementSibling.style.visibility = 'collapse'; this.button.innerText = 'Show'; } } }) })();</script>

Page 90: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <button>Hide</button></template>

<script> (function() { var ctx = new Context();

newElement('toggle-next', { createdCallback: function() { this.appendChild(ctx.import('t')); this.button = this.querySelector('button'); this.button.addEventListener('click', this._buttonClick.bind(this)); },

_buttonClick: function() { var current = this.nextElementSibling.style.visibility; if (current == 'collapse') { this.nextElementSibling.style.visibility = 'visible'; this.button.innerText = 'Hide'; } else { this.nextElementSibling.style.visibility = 'collapse'; this.button.innerText = 'Show'; } } }) })();</script>

Page 91: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <button>Hide</button></template>

<script> (function() { var ctx = new Context();

newElement('toggle-next', { createdCallback: function() { this.appendChild(ctx.import('t')); this.button = this.querySelector('button'); this.button.addEventListener('click', this._buttonClick.bind(this)); },

_buttonClick: function() { var current = this.nextElementSibling.style.visibility; if (current == 'collapse') { this.nextElementSibling.style.visibility = 'visible'; this.button.innerText = 'Hide'; } else { this.nextElementSibling.style.visibility = 'collapse'; this.button.innerText = 'Show'; } } }) })();</script>

Page 92: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <button>Hide</button></template>

<script> (function() { var ctx = new Context();

newElement('toggle-next', { createdCallback: function() { this.appendChild(ctx.import('t')); this.button = this.querySelector('button'); this.button.addEventListener('click', this._buttonClick.bind(this)); },

_buttonClick: function() { var current = this.nextElementSibling.style.visibility; if (current == 'collapse') { this.nextElementSibling.style.visibility = 'visible'; this.button.innerText = 'Hide'; } else { this.nextElementSibling.style.visibility = 'collapse'; this.button.innerText = 'Show'; } } }) })();</script>

Page 93: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <button>Hide</button></template>

<script> (function() { var ctx = new Context();

newElement('toggle-next', { createdCallback: function() { this.appendChild(ctx.import('t')); this.button = this.querySelector('button'); this.button.addEventListener('click', this._buttonClick.bind(this)); },

_buttonClick: function() { var current = this.nextElementSibling.style.visibility; if (current == 'collapse') { this.nextElementSibling.style.visibility = 'visible'; this.button.innerText = 'Hide'; } else { this.nextElementSibling.style.visibility = 'collapse'; this.button.innerText = 'Show'; } } }) })();</script>

Page 94: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <button>Hide</button></template>

<script> (function() { var ctx = new Context();

NewElement('toggle-next', { createdCallback: function() { this.appendChild(ctx.import('t')); this.button = this.querySelector('button'); this.button.addEventListener('click', this._buttonClick.bind(this)); },

_buttonClick: function() { var current = this.nextElementSibling.style.visibility; if (current == 'collapse') { this.nextElementSibling.style.visibility = 'visible'; this.button.innerText = 'Hide'; } else { this.nextElementSibling.style.visibility = 'collapse'; this.button.innerText = 'Show'; } } }) })();</script>

Page 95: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <button>Hide</button></template>

<script> (function() { var ctx = new Context();

newElement('toggle-next', { createdCallback: function() { this.appendChild(ctx.import('t')); this.button = this.querySelector('button'); this.button.addEventListener('click', this._buttonClick.bind(this)); },

_buttonClick: function() { var current = this.nextElementSibling.style.visibility; if (current == 'collapse') { this.nextElementSibling.style.visibility = 'visible'; this.button.innerText = 'Hide'; } else { this.nextElementSibling.style.visibility = 'collapse'; this.button.innerText = 'Show'; } } }) })();</script>

Page 96: 2016 stop writing javascript frameworks by Joe Gregorio

<!DOCTYPE html><html>

<head> <script src="webcomponents.js"></script> <script src="util.js"></script> <link rel="import" href="toggle.html"></head>

<body> <toggle-next></toggle-next> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi dignissim, nisi non rhoncus condimentum, felis ante porta eros, ut tincidunt odio nisl a libero. </p></body>

</html>

Page 97: 2016 stop writing javascript frameworks by Joe Gregorio

<!DOCTYPE html><html>

<head> <script src="webcomponents.js"></script> <script src="util.js"></script> <link rel="import" href="toggle.html"></head>

<body> <toggle-next></toggle-next> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi dignissim, nisi non rhoncus condimentum, felis ante porta eros, ut tincidunt odio nisl a libero. </p></body>

</html>

Page 98: 2016 stop writing javascript frameworks by Joe Gregorio

<!DOCTYPE html><html>

<head> <script src="webcomponents.js"></script> <script src="util.js"></script> <link rel="import" href="toggle.html"></head>

<body> <toggle-next></toggle-next> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi dignissim, nisi non rhoncus condimentum, felis ante porta eros, ut tincidunt odio nisl a libero. </p></body>

</html>

Page 99: 2016 stop writing javascript frameworks by Joe Gregorio

<!DOCTYPE html><html>

<head> <script src="webcomponents.js"></script> <script src="util.js"></script> <link rel="import" href="toggle.html"></head>

<body> <toggle-next></toggle-next> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi dignissim, nisi non rhoncus condimentum, felis ante porta eros, ut tincidunt odio nisl a libero. </p></body>

</html>

Page 100: 2016 stop writing javascript frameworks by Joe Gregorio

<!DOCTYPE html><html>

<head> <script src="webcomponents.js"></script> <script src="util.js"></script> <link rel="import" href="toggle.html"></head>

<body> <toggle-next></toggle-next> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi dignissim, nisi non rhoncus condimentum, felis ante porta eros, ut tincidunt odio nisl a libero. </p></body>

</html>

bit.ly/zf-toggle

Page 101: 2016 stop writing javascript frameworks by Joe Gregorio

So how did this work?

Adjacency in the DOM tree.

Page 102: 2016 stop writing javascript frameworks by Joe Gregorio

Framework

Polyfills Web Components

Fill in the potholes.

Code organization

Page 103: 2016 stop writing javascript frameworks by Joe Gregorio

Organizing around the surfaces already present in the browser.

Page 104: 2016 stop writing javascript frameworks by Joe Gregorio

● Attributes

● Events

● DOM Structure

Page 105: 2016 stop writing javascript frameworks by Joe Gregorio

<button id=submit>Submit</button>

document.querySelector('#submit').id

document.querySelector('#submit').click()

Attributes

Page 106: 2016 stop writing javascript frameworks by Joe Gregorio

<button id=submit>Submit</button>

document.querySelector('#submit').id

document.querySelector('#submit').click()

Attributes

Page 107: 2016 stop writing javascript frameworks by Joe Gregorio

<button id=submit>Submit</button>

document.querySelector('#submit').id

document.querySelector('#submit').click()

Attributes

Page 108: 2016 stop writing javascript frameworks by Joe Gregorio

<button id=submit>Submit</button>

document.querySelector('#submit').id

document.querySelector('#submit').click()

Attributes

Page 109: 2016 stop writing javascript frameworks by Joe Gregorio

ele.addEventListener('some-event', function(e) { /* */ });

var e = new CustomEvent('some-event', {details: details});this.dispatchEvent(e);

Events

Page 110: 2016 stop writing javascript frameworks by Joe Gregorio

ele.addEventListener('some-event', function(e) { /* */ });

var e = new CustomEvent('some-event', {details: details});this.dispatchEvent(e);

Events

Page 111: 2016 stop writing javascript frameworks by Joe Gregorio

ele.addEventListener('some-event', function(e) { /* */ });

var e = new CustomEvent('some-event', {details: details});this.dispatchEvent(e);

Events

Page 112: 2016 stop writing javascript frameworks by Joe Gregorio

<button> <img src=""></button>

<div> <p class=foo></p> <p class=foo></p> <p class=foo></p> <p class=bar></p></div>

DOM Structure

Page 113: 2016 stop writing javascript frameworks by Joe Gregorio

<button> <img src=""> Parent/Child</button>

<div> <p class=foo></p> <p class=foo></p> <p class=foo></p> <p class=bar></p></div>

DOM Structure

Page 114: 2016 stop writing javascript frameworks by Joe Gregorio

<button> <img src=""></button>

<div> <p class=foo></p> <p class=foo></p> CSS Selectors <p class=foo></p> querySelector('.foo') <p class=bar></p></div>

DOM Structure

Page 115: 2016 stop writing javascript frameworks by Joe Gregorio

A more detailed example

Page 116: 2016 stop writing javascript frameworks by Joe Gregorio
Page 117: 2016 stop writing javascript frameworks by Joe Gregorio

<sort-stuff data-target="#sortable"> <button data-key=pop>Sort on Population</button> <button data-key=density>Sort on Density</button> <button data-key=change>Sort on % Change</button></sort-stuff>

<ul id=sortable> <li data-pop=8.4 data-density=27000 data-change=3.86>New York</li> <li data-pop=3.9 data-density=8092 data-change=3.59>Los Angeles</li> <li data-pop=2.7 data-density=11842 data-change=0.99>Chicago</li> <li data-pop=2.2 data-density=3501 data-change=6.63>Houston</li> <li data-pop=1.5 data-density=11379 data-change=2.25>Philadelphia</li></ul>

Page 118: 2016 stop writing javascript frameworks by Joe Gregorio

<sort-stuff data-target="#sortable"> <button data-key=pop>Sort on Population</button> <button data-key=density>Sort on Density</button> <button data-key=change>Sort on % Change</button></sort-stuff>

<ul id=sortable> <li data-pop=8.4 data-density=27000 data-change=3.86>New York</li> <li data-pop=3.9 data-density=8092 data-change=3.59>Los Angeles</li> <li data-pop=2.7 data-density=11842 data-change=0.99>Chicago</li> <li data-pop=2.2 data-density=3501 data-change=6.63>Houston</li> <li data-pop=1.5 data-density=11379 data-change=2.25>Philadelphia</li></ul>

Page 119: 2016 stop writing javascript frameworks by Joe Gregorio

<sort-stuff data-target="#sortable"> <button data-key=pop>Sort on Population</button> <button data-key=density>Sort on Density</button> <button data-key=change>Sort on % Change</button></sort-stuff>

<ul id=sortable> <li data-pop=8.4 data-density=27000 data-change=3.86>New York</li> <li data-pop=3.9 data-density=8092 data-change=3.59>Los Angeles</li> <li data-pop=2.7 data-density=11842 data-change=0.99>Chicago</li> <li data-pop=2.2 data-density=3501 data-change=6.63>Houston</li> <li data-pop=1.5 data-density=11379 data-change=2.25>Philadelphia</li></ul>

Page 120: 2016 stop writing javascript frameworks by Joe Gregorio

<sort-stuff data-target="#sortable"> <button data-key=pop>Sort on Population</button> <button data-key=density>Sort on Density</button> <button data-key=change>Sort on % Change</button></sort-stuff>

<ul id=sortable> <li data-pop=8.4 data-density=27000 data-change=3.86>New York</li> <li data-pop=3.9 data-density=8092 data-change=3.59>Los Angeles</li> <li data-pop=2.7 data-density=11842 data-change=0.99>Chicago</li> <li data-pop=2.2 data-density=3501 data-change=6.63>Houston</li> <li data-pop=1.5 data-density=11379 data-change=2.25>Philadelphia</li></ul>

Page 121: 2016 stop writing javascript frameworks by Joe Gregorio

<sort-stuff data-target="#sortable"> <button data-key=pop>Sort on Population</button> <button data-key=density>Sort on Density</button> <button data-key=change>Sort on % Change</button></sort-stuff>

<ul id=sortable> <li data-pop=8.4 data-density=27000 data-change=3.86>New York</li> <li data-pop=3.9 data-density=8092 data-change=3.59>Los Angeles</li> <li data-pop=2.7 data-density=11842 data-change=0.99>Chicago</li> <li data-pop=2.2 data-density=3501 data-change=6.63>Houston</li> <li data-pop=1.5 data-density=11379 data-change=2.25>Philadelphia</li></ul>

Page 122: 2016 stop writing javascript frameworks by Joe Gregorio

newElement('sort-stuff', { createdCallback : function() { this.addEventListener( 'click', this._clickHandler.bind( this)); },

_clickHandler : function(e) { ... }, });

Page 123: 2016 stop writing javascript frameworks by Joe Gregorio

newElement('sort-stuff', { createdCallback : function() { this.addEventListener( 'click', this._clickHandler.bind( this)); },

_clickHandler: function(e) { ... }, });

Page 124: 2016 stop writing javascript frameworks by Joe Gregorio

_clickHandler: function(e) { var key = e.target.dataset.key; if (!key) { return; } var target = document.querySelector(this.dataset.target); var elements = []; var children = target.children; for (var i=0; i<children.length; i++) { var ele = children[i]; elements.push({ value: +ele.dataset[key], node: ele, }); } elements.sort(function(x, y) { return (x.value == y.value ? 0 : (x.value < y.value ? 1 : -1)); }); elements.forEach(function(i) { target.appendChild(i.node); }); },

Page 125: 2016 stop writing javascript frameworks by Joe Gregorio

_clickHandler: function(e) { var key = e.target.dataset.key; if (!key) { return; } var target = document.querySelector(this.dataset.target); var elements = []; var children = target.children; for (var i=0; i<children.length; i++) { var ele = children[i]; elements.push({ value: +ele.dataset[key], node: ele, }); } elements.sort(function(x, y) { return (x.value == y.value ? 0 : (x.value < y.value ? 1 : -1)); }); elements.forEach(function(i) { target.appendChild(i.node); }); },

Page 126: 2016 stop writing javascript frameworks by Joe Gregorio

_clickHandler: function(e) { var key = e.target.dataset.key; if (!key) { return; } var target = document.querySelector(this.dataset.target); var elements = []; var children = target.children; for (var i=0; i<children.length; i++) { var ele = children[i]; elements.push({ value: +ele.dataset[key], node: ele, }); } elements.sort(function(x, y) { return (x.value == y.value ? 0 : (x.value < y.value ? 1 : -1)); }); elements.forEach(function(i) { target.appendChild(i.node); }); },

Page 127: 2016 stop writing javascript frameworks by Joe Gregorio

_clickHandler: function(e) { var key = e.target.dataset.key; if (!key) { return; } var target = document.querySelector(this.dataset.target); var elements = []; var children = target.children; for (var i=0; i<children.length; i++) { var ele = children[i]; elements.push({ value: +ele.dataset[key], node: ele, }); } elements.sort(function(x, y) { return (x.value == y.value ? 0 : (x.value < y.value ? 1 : -1)); }); elements.forEach(function(i) { target.appendChild(i.node); }); },

Page 129: 2016 stop writing javascript frameworks by Joe Gregorio

● sort-stuff has 'data-target' [Attribute] that selects [DOM Structure] the element

to sort.

● The target children [DOM Structure] have data attributes [Attribute] that

elements are sorted on.

● sort-stuff registers for a 'click' [Events] from its children [DOM Structure].

● sort-stuff children [DOM Structure] have data attributes [Attribute] that

determine how the target children will be sorted.

Surfaces Used

Page 130: 2016 stop writing javascript frameworks by Joe Gregorio

● sort-stuff doesn't care what its children are, only that they generate 'click'

events and the 'click' generating elements have the 'data-key' attributes.

● sort-stuff doesn't care what the elements found at data-target are, only that it

has children that have data-"key" attributes.

Only Surfaces Are Used

Page 131: 2016 stop writing javascript frameworks by Joe Gregorio

● Change the children of <sort-stuff>

● Change the children of sort-stuff.data-target.

Only Surfaces Are Used

Page 132: 2016 stop writing javascript frameworks by Joe Gregorio

<sort-stuff data-target="#sortable"> <p><input type=radio name=sort data-key=pop /> Population</p> <p><input type=radio name=sort data-key=density /> Density</p> <p><input type=radio name=sort data-key=change /> % Change</p> <sort-stuff>

<table> <tbody id=sortable> <tr data-pop=8.4 data-density=27000 data-change=3.86><td>New York</td></tr> <tr data-pop=3.9 data-density=8092 data-change=3.59><td>Los Angeles</td></tr> <tr data-pop=2.7 data-density=11842 data-change=0.99><td>Chicago</td></tr> <tr data-pop=2.2 data-density=3501 data-change=6.63><td>Houston</td></tr> <tr data-pop=1.5 data-density=11379 data-change=2.25><td>Philadelphia</td></tr> </tbody> </table>

Page 134: 2016 stop writing javascript frameworks by Joe Gregorio

Roll in toggle-next

Page 136: 2016 stop writing javascript frameworks by Joe Gregorio

Framework

Polyfills Web Components

Packaging: HTML ImportsOrganization:

EventsAttributesDOM Structure

Page 137: 2016 stop writing javascript frameworks by Joe Gregorio

Summary

Page 138: 2016 stop writing javascript frameworks by Joe Gregorio

Start writing reusable orthogonally composable units of HTML+CSS+JS

Page 139: 2016 stop writing javascript frameworks by Joe Gregorio

http://bit.ly/100-line-template

Data Binding

Page 140: 2016 stop writing javascript frameworks by Joe Gregorio

<template id=t> <div> <p><a href="{{ url }}">{{ foo.bar.baz }} {{ quux }}</a>!</p> <!-- Loop over arrays. Use data attributes of data-repeat-[name]="{{ x.y.z }}" and reference the values iterated over using {{ [name] }}. For arrays the 'i' state variable is also set. --> <ul data-repeat-num="{{ list }}"> <li>{{ num }} {{ i }}</li> </ul> <!-- Loop over Objects. For objects the 'key' state variable is also set. --> <ul data-repeat-o="{{ anobj }}"> <li>{{ key }}={{ o.name }}</li> </ul> </div> </template>

Page 141: 2016 stop writing javascript frameworks by Joe Gregorio

var clone = ctx.import('t');

Expand(clone, data);

document.body.appendChild(clone);

Page 142: 2016 stop writing javascript frameworks by Joe Gregorio

Extra Benefits

● Enabling mix and match (our use of D3.js).

● Better than native. (support and styling).○ Ever tried to style a checkbox?○ details/summary

■ http://caniuse.com/#feat=details

Page 143: 2016 stop writing javascript frameworks by Joe Gregorio
Page 144: 2016 stop writing javascript frameworks by Joe Gregorio

Missing Pieces

Page 145: 2016 stop writing javascript frameworks by Joe Gregorio

● CSS Variables for Shadow DOM

● Better Compilers

Page 146: 2016 stop writing javascript frameworks by Joe Gregorio
Page 147: 2016 stop writing javascript frameworks by Joe Gregorio

There are dozens of us!

● You (probably) don't need a JavaScript framework https://slack-files.com/T03JT4FC2-F151AAF7A-13fe6f98da

Page 148: 2016 stop writing javascript frameworks by Joe Gregorio

fin

Page 149: 2016 stop writing javascript frameworks by Joe Gregorio

Appendix

Page 150: 2016 stop writing javascript frameworks by Joe Gregorio

● http://webcomponents.org/polyfills/○ You only need webcomponents-lite.js for all the content in this slide

deck. ● http://bitworking.org/news/2014/05/zero_framework_manifesto

○ The rant that launched it all. ● http://vanilla-js.com/

Page 151: 2016 stop writing javascript frameworks by Joe Gregorio

But what about React Native?“learn once, write anywhere.“

https://en.wikipedia.org/wiki/List_of_platform-independent_GUI_libraries