SlideShare une entreprise Scribd logo
1  sur  157
Télécharger pour lire hors ligne
Why you should be using Web Components Now.
And How.
PHIL @LEGGETTER
Head of Developer Relations
1 / 157
2 / 157
3 / 157
What we'll cover
What are Web Components?
The State of Web Components
Componentised Web Apps Now
Why Web Components are the Future!
4 / 157
What are Web Components?
5 / 157
What are Web Components?
Custom Elements
HTML Templates
Shadow DOM
HTML Imports
6 / 157
Custom Elements
7 / 157
Elements - Structure & Meaning
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>HTML Elements</title>
<meta name="description" content="" />
<link rel="stylesheet" href="css/stylez.css" />
</head>
<body>
<nav>
<ul>
<li><a href="#">Home</a></li>
</ul>
</nav>
<header>
<p>Hello world! This (part of) is HTML5 Boilerplate.</p>
</header>
<main>
<article>Ohhhh. Interesting</article>
</main>
<footer>&copy; me</footer>
<script src="js/script.js"></script>
</body>
</html>
8 / 157
Elements in "apps"
9 / 157
Elements. Arrrgghhh!
10 / 157
<Custom Elements />
11 / 157
<Custom Elements />
Bring semantic markup back
More than just markup
IMHO the most important part of Web Components
12 / 157
Custom Elements: A new Gmail
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>A new Gmail?</title>
<meta name="description" content="">
</head>
<body>
13 / 157
Custom Elements: A new Gmail
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>A new Gmail?</title>
<meta name="description" content="">
</head>
<body>
<header>
<img src="img/logo.png" alt="Google Logo" />
<gmail-search />
<gmail-account-strip />
</header>
14 / 157
Custom Elements: A new Gmail
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>A new Gmail?</title>
<meta name="description" content="">
</head>
<body>
<header>
<img src="img/logo.png" alt="Google Logo" />
<gmail-search />
<gmail-account-strip />
</header>
<gmail-side-bar>
<nav is="gmail-labels"></nav>
<gmail-contacts />
</gmail-sidebar>
15 / 157
Custom Elements: A new Gmail
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>A new Gmail?</title>
<meta name="description" content="">
</head>
<body>
<header>
<img src="img/logo.png" alt="Google Logo" />
<gmail-search />
<gmail-account-strip />
</header>
<gmail-side-bar>
<nav is="gmail-labels"></nav>
<gmail-contacts />
</gmail-sidebar>
<main>
<nav is="gmail-categories"></nav>
<gmail-email-list />
</main>
16 / 157
Custom Elements: A new Gmail
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>A new Gmail?</title>
<meta name="description" content="">
</head>
<body>
<header>
<img src="img/logo.png" alt="Google Logo" />
<gmail-search />
<gmail-account-strip />
</header>
<gmail-side-bar>
<nav is="gmail-labels"></nav>
<gmail-contacts />
</gmail-sidebar>
<main>
<nav is="gmail-categories"></nav>
<gmail-email-list />
</main>
<hangouts />
</body>
</html>
17 / 157
Tools, Tips & Tricks for building
Componentised Web Apps
18 / 157
<img src="http://avatars.io/twitter/leggetter" />
<img src="http://avatars.io/instagram/leggetter" />
<img src="http://avatars.io/gravatar/phil@pusher.com" />
<img src="http://api.skype.com/users/pleggetter/profile/avatar" />
Start Simple - An Avatar
19 / 157
Custom Elements
<my-avatar service="twitter" username="leggetter" />
20 / 157
Custom Elements
<my-avatar service="twitter" username="leggetter" />
<script>
var MyAvatarPrototype = Object.create(HTMLElement.prototype);
21 / 157
Custom Elements
<my-avatar service="twitter" username="leggetter" />
<script>
var MyAvatarPrototype = Object.create(HTMLElement.prototype);
MyAvatarPrototype.createdCallback = function() {
var username = this.getAttribute('username');
var service = this.getAttribute('service');
22 / 157
Custom Elements
<my-avatar service="twitter" username="leggetter" />
<script>
var MyAvatarPrototype = Object.create(HTMLElement.prototype);
MyAvatarPrototype.createdCallback = function() {
var username = this.getAttribute('username');
var service = this.getAttribute('service');
var url = 'http://avatars.io/' + service + '/' + username;
23 / 157
Custom Elements
<my-avatar service="twitter" username="leggetter" />
<script>
var MyAvatarPrototype = Object.create(HTMLElement.prototype);
MyAvatarPrototype.createdCallback = function() {
var username = this.getAttribute('username');
var service = this.getAttribute('service');
var url = 'http://avatars.io/' + service + '/' + username;
var img = document.createElement( 'img' );
img.setAttribute('src', url);
this.appendChild(img);
};
24 / 157
Custom Elements
<my-avatar service="twitter" username="leggetter" />
<script>
var MyAvatarPrototype = Object.create(HTMLElement.prototype);
MyAvatarPrototype.createdCallback = function() {
var username = this.getAttribute('username');
var service = this.getAttribute('service');
var url = 'http://avatars.io/' + service + '/' + username;
var img = document.createElement( 'img' );
img.setAttribute('src', url);
this.appendChild(img);
};
document.registerElement('my-avatar', {
prototype: MyAvatarPrototype
});
</script>
Define your own elements. 25 / 157
<my-avatar service="twitter" username="leggetter" />
<my-avatar service="instagram" username="leggetter" />
<my-avatar service="twitter" username="forwardjs" />
<my-avatar />
26 / 157
Custom Elements - Extending
<img is="my-avatar-ext" service="twitter" username="leggetter" />
27 / 157
Custom Elements - Extending
<img is="my-avatar-ext" service="twitter" username="leggetter" />
<script>
var MyAvatarExtPrototype = Object.create(HTMLImageElement.prototype);
28 / 157
Custom Elements - Extending
<img is="my-avatar-ext" service="twitter" username="leggetter" />
<script>
var MyAvatarExtPrototype = Object.create(HTMLImageElement.prototype);
MyAvatarExtPrototype.createdCallback = function() {
var username = this.getAttribute('username'),
service = this.getAttribute('service'),
url = 'http://avatars.io/' + service + '/' + username;
this.setAttribute('src', url);
};
29 / 157
Custom Elements - Extending
<img is="my-avatar-ext" service="twitter" username="leggetter" />
<script>
var MyAvatarExtPrototype = Object.create(HTMLImageElement.prototype);
MyAvatarExtPrototype.createdCallback = function() {
var username = this.getAttribute('username'),
service = this.getAttribute('service'),
url = 'http://avatars.io/' + service + '/' + username;
this.setAttribute('src', url);
};
document.registerElement('my-avatar-ext', {
prototype: MyAvatarExtPrototype,
extends: 'img'
});
</script>
Extending existing elements
30 / 157
Custom Elements - Lifecycle
createdCallback
attachedCallback
detachedCallback
attributeChangedCallback(attrName, oldVal,
newVal)
31 / 157
Create Elements using JavaScript
<script>
function createPhils() {
var tooManyPhils = 104;
var phils = 0;
do {
var el = document.createElement( 'my-avatar' );
el.setAttribute('service', 'twitter');
el.setAttribute('username', 'leggetter');
document.getElementById( 'phils' ).appendChild( el );
++phils;
} while( phils < tooManyPhils );
}
</script>
Create Phils
32 / 157
Why Custom Elements?
33 / 157
Templates
Native HTML Templating Support
34 / 157
<script type="text/x-handlebars-template">
<div class="entry">
<h1>{{title}}</h1>
<div>{{body}}</div>
</div>
</script>
35 / 157
HTML Templates Create Avatar
<template id="my-avatar-template">
<style>
.container { background-color: gold; }
<!-- omitted for brevity -->
</style>
<div class="container">
<img class="avatar" />
<span class="username"></span>
<span class="service"></span>
</div>
</template>
36 / 157
HTML Templates Create Avatar
<template id="my-avatar-template">
<style>
.container { background-color: gold; }
<!-- omitted for brevity -->
</style>
<div class="container">
<img class="avatar" />
<span class="username"></span>
<span class="service"></span>
</div>
</template>
var MyAvatarTmplPrototype = Object.create(HTMLElement.prototype);
MyAvatarTmplPrototype.createdCallback = function() {
// get attributes & build url
37 / 157
HTML Templates Create Avatar
<template id="my-avatar-template">
<style>
.container { background-color: gold; }
<!-- omitted for brevity -->
</style>
<div class="container">
<img class="avatar" />
<span class="username"></span>
<span class="service"></span>
</div>
</template>
var MyAvatarTmplPrototype = Object.create(HTMLElement.prototype);
MyAvatarTmplPrototype.createdCallback = function() {
// get attributes & build url
var content = document.querySelector( '#my-avatar-template' ).content;
var el = document.importNode( content, true );
38 / 157
HTML Templates Create Avatar
<template id="my-avatar-template">
<style>
.container { background-color: gold; }
<!-- omitted for brevity -->
</style>
<div class="container">
<img class="avatar" />
<span class="username"></span>
<span class="service"></span>
</div>
</template>
var MyAvatarTmplPrototype = Object.create(HTMLElement.prototype);
MyAvatarTmplPrototype.createdCallback = function() {
// get attributes & build url
var content = document.querySelector( '#my-avatar-template' ).content;
var el = document.importNode( content, true );
el.querySelector( '.avatar' ).setAttribute( 'src', url );
el.querySelector( '.username' ).textContent = username;
el.querySelector( '.service' ).textContent = service;
this.appendChild( el );
};
39 / 157
HTML Templates Create Avatar
<template id="my-avatar-template">
<style>
.container { background-color: gold; }
<!-- omitted for brevity -->
</style>
<div class="container">
<img class="avatar" />
<span class="username"></span>
<span class="service"></span>
</div>
</template>
var MyAvatarTmplPrototype = Object.create(HTMLElement.prototype);
MyAvatarTmplPrototype.createdCallback = function() {
// get attributes & build url
var content = document.querySelector( '#my-avatar-template' ).content;
var el = document.importNode( content, true );
el.querySelector( '.avatar' ).setAttribute( 'src', url );
el.querySelector( '.username' ).textContent = username;
el.querySelector( '.service' ).textContent = service;
this.appendChild( el );
};
document.registerElement('my-avatar-tmpl', {
prototype: MyAvatarTmplPrototype
40 / 157
Why native HTML Templates?
Libraries → Native
Native benefits
Document fragment = lightweight
Inert until cloned/used
41 / 157
Shadow DOM
DOM/CSS "scoping" / protection
42 / 157
Shadow DOM - Already using it
43 / 157
Shadow DOM - Problems it solves
44 / 157
Styles <span class="container">Bleed!</span>
<template id="my-avatar-tmpl">
<style>
.container { background-color: cyan; }
...
<my-avatar-tmpl service="twitter" username="leggetter" />
Styles Bleed! Create
Shadow DOM - Problems it solves
45 / 157
Styles <span class="container">Bleed!</span>
<template id="my-avatar-tmpl">
<style>
.container { background-color: cyan; }
...
<my-avatar-tmpl service="twitter" username="leggetter" />
Styles Bleed! Create
<template id="my-avatar-template">
<div class="container">
<img id="avatar" />
...
</template>
Global DOM
e.g. id attributes
Shadow DOM - Problems it solves
46 / 157
Shadow DOM - In Action Create ForwardJS
47 / 157
Shadow DOM - In Action Create ForwardJS
<template id="my-avatar-shadow-tmpl">
<style>
.container { background-color: red; color: white; }
...
</style>
<div class="container">
<img id="avatar" />
...
</div>
</template>
48 / 157
Shadow DOM - In Action Create ForwardJS
<template id="my-avatar-shadow-tmpl">
<style>
.container { background-color: red; color: white; }
...
</style>
<div class="container">
<img id="avatar" />
...
</div>
</template>
var MyAvatarShadowPrototype = Object.create(HTMLElement.prototype);
MyAvatarShadowPrototype.createdCallback = function() {
// get attributes & build url
var content = document.querySelector( '#my-avatar-shadow-tmpl' ).content;
49 / 157
Shadow DOM - In Action Create ForwardJS
<template id="my-avatar-shadow-tmpl">
<style>
.container { background-color: red; color: white; }
...
</style>
<div class="container">
<img id="avatar" />
...
</div>
</template>
var MyAvatarShadowPrototype = Object.create(HTMLElement.prototype);
MyAvatarShadowPrototype.createdCallback = function() {
// get attributes & build url
var content = document.querySelector( '#my-avatar-shadow-tmpl' ).content;
this.shadow = this.createShadowRoot();
this.shadow.appendChild( document.importNode( content, true ) );
50 / 157
Shadow DOM - In Action Create ForwardJS
<template id="my-avatar-shadow-tmpl">
<style>
.container { background-color: red; color: white; }
...
</style>
<div class="container">
<img id="avatar" />
...
</div>
</template>
var MyAvatarShadowPrototype = Object.create(HTMLElement.prototype);
MyAvatarShadowPrototype.createdCallback = function() {
// get attributes & build url
var content = document.querySelector( '#my-avatar-shadow-tmpl' ).content;
this.shadow = this.createShadowRoot();
this.shadow.appendChild( document.importNode( content, true ) );
this.shadow.querySelector( '#avatar' ).setAttribute( 'src', url );
this.shadow.querySelector( '#username' ).textContent = username;
this.shadow.querySelector( '#service' ).textContent = service;
};
51 / 157
Shadow DOM - In Action Create ForwardJS
<template id="my-avatar-shadow-tmpl">
<style>
.container { background-color: red; color: white; }
...
</style>
<div class="container">
<img id="avatar" />
...
</div>
</template>
var MyAvatarShadowPrototype = Object.create(HTMLElement.prototype);
MyAvatarShadowPrototype.createdCallback = function() {
// get attributes & build url
var content = document.querySelector( '#my-avatar-shadow-tmpl' ).content;
this.shadow = this.createShadowRoot();
this.shadow.appendChild( document.importNode( content, true ) );
this.shadow.querySelector( '#avatar' ).setAttribute( 'src', url );
this.shadow.querySelector( '#username' ).textContent = username;
this.shadow.querySelector( '#service' ).textContent = service;
};
document.registerElement('my-avatar-shadow', {
prototype: MyAvatarShadowPrototype
52 / 157
Why Shadow DOM?
DOM & CSS Scoping
Protection for all: Page and Element
Encapsulation
53 / 157
HTML Imports
Loading & Dependency Management
54 / 157
HTML Imports - Example
Before
<link rel="stylesheet" href="bootstrap.css" />
<link rel="stylesheet" href="fonts.css" />
<script src="jquery.js"></script>
<script src="bootstrap.js"></script>
<script src="bootstrap-tooltip.js"></script>
<script src="bootstrap-dropdown.js"></script>
55 / 157
HTML Imports - Example
Before
<link rel="stylesheet" href="bootstrap.css" />
<link rel="stylesheet" href="fonts.css" />
<script src="jquery.js"></script>
<script src="bootstrap.js"></script>
<script src="bootstrap-tooltip.js"></script>
<script src="bootstrap-dropdown.js"></script>
After
<link rel="import" href="bootstrap.html" />
56 / 157
HTML Imports - Composition
team-pusher.html
57 / 157
HTML Imports - Composition
team-pusher.html
<link rel="import" href="my-avatar-import.html" />
58 / 157
HTML Imports - Composition
team-pusher.html
<link rel="import" href="my-avatar-import.html" />
<template id="team-pusher-tmpl">
<style> </style>
<my-avatar-import service="twitter" username="maxthelion" />
<my-avatar-import service="twitter" username="copypastaa" />
...
<my-avatar-import service="twitter" username="leggetter" />
</template>
...
59 / 157
HTML Imports - Composition
team-pusher.html
<link rel="import" href="my-avatar-import.html" />
<template id="team-pusher-tmpl">
<style> </style>
<my-avatar-import service="twitter" username="maxthelion" />
<my-avatar-import service="twitter" username="copypastaa" />
...
<my-avatar-import service="twitter" username="leggetter" />
</template>
<script>
var TeamPusherPrototype = Object.create(HTMLElement.prototype);
TeamPusherPrototype.createdCallback = function() {
// Get template, createShadowRoot etc.
};
document.registerElement('team-pusher', {
prototype: TeamPusherPrototype
});
</script>
...
60 / 157
HTML Imports - Composition Demo
<link rel="import" href="assets/team-pusher.html" />
<team-pusher></team-pusher>
61 / 157
HTML Imports - Composition Demo
<link rel="import" href="assets/team-pusher.html" />
<team-pusher></team-pusher>
maxthelion
twitter
copypastaa
twitter
zimbatm
twitter
loicdumas
twitter
mdpye
twitter
olga_dukova
twitter
pawel_ledwon
twitter
hamchapman
twitter
LaurieWang_
twitter
swstagg
twitter
vivangkumar
twitter
willsewell_
twitter
davidrbiggs
twitter
leggetter
twitter
We're Hiring! pusher.com/jobs
62 / 157
Why Use HTML Imports?
Bundle JS/HTML/CSS → single URL
Basic dependency management
Sharing, Reuse, Composition
63 / 157
Gotchas / Patterns!
64 / 157
Get & use document from the currentScript
( function( currentScript ) {
var importDoc = currentScript.ownerDocument;
TeamPusherPrototype.createdCallback = function() {
var content = importDoc.querySelector( '#team-pusher-tmpl' ).content;
// ...
};
} )( document._currentScript || document.currentScript );
65 / 157
importNode and NOT cloneNode for Template
// Note: use ownerDoc
var content = ownerDoc.querySelector( '#my-template' );
var clone = ownerDoc.importNode( content, true );
66 / 157
You can't <link> into the Shadow DOM
<template>
<link rel="stylesheet" href="path/to/style.css" />
</template>
67 / 157
The State of...
68 / 157
The State of Custom Elements
is
Concerns around Accessibility
Point of Upgrade
When HTMLElement is transformed into Custom Element
69 / 157
The State of Templates ✔
70 / 157
The State of Shadow DOM
<content select="tag" />
Declarative element content placement
71 / 157
The State of Shadow DOM
<content select="tag" />
Declarative element content placement
element.createShadowRoot({ mode:
'closed' });
protecting shadowRoot
72 / 157
The State of Shadow DOM
<content select="tag" />
Declarative element content placement
element.createShadowRoot({ mode:
'closed' });
protecting shadowRoot
.foo >>> div { color: red }
Shadow piercing combinators
...
73 / 157
The State of HTML Imports
74 / 157
Firefox
https://hacks.mozilla.org/2014/12/mozilla-and-web-components/
“Mozilla will not ship an implementation of
HTML Imports. We expect that once JavaScript
modules ... is shipped, the way we look at this
problem will have changed.
75 / 157
Essential "State of" Reading
Wilson Page - The State of Web Components
Microsoft Edge Team - Bringing componentization to the web: An
overview of Web Components
76 / 157
The State of Browsers
77 / 157
Microsoft Edge
78 / 157
Apple's updated feedback on Custom Elements and Shadow DOM
From: Maciej Stachowiak <mjs@apple.com>
Date: Mon, 20 Jul 2015 18:17:24 -0700
Message-id: <E9841AA1-9255-4324-946E-E785B15DAE93@apple.com>
To: public-webapps <public-webapps@w3.org>
A while back we sent a consolidated pile of feedback on the Web Components family of specs. In preparation for tomorrow's F2F, here is an update on
our positions. We've also changed the bugzilla links to point to relevant github issues instead.
We're only covering Custom Elements (the main expected topic), and also Shadow DOM (in case that gets discussed too).
I. ==== Custom Elements ====
A. ES6 classes / Upgrade / Synchronous Constructors
1. In general, we support the "synchronous constructors" approach to the "prototype swizzling" approach, as the lesser evil. While
tricky to implement correctly, it makes a lot more sense and fits more naturally into the language. We are willing to do the work to make it
feasible.
2. Custom elements should support initialization using an ES6 class constructo instead of a separate callback.
<https://github.com/w3c/webcomponents/issues/139 <https://www.w3.org/Bugs/Public/show_bug.cgi?id=28541>>
3. We don’t think upgrading should be supported. The tradeoffs of different options have been much-discussed.
<https://github.com/w3c/webcomponents/issues/134 <https://www.w3.org/Bugs/Public/show_bug.cgi?id=28544>>
4. Specifically, we don't really like the "Optional Upgrades, Optional Constructors" proposal (seems like it's the worst of both
worlds in terms of complexity and weirdness) or the "Parser-Created Classes" proposal (not clear how this even solves the problem).
B. Insertion/Removal Callbacks
1. We think the current attached/detached callbacks should be removed. They don’t match core DOM concepts and insert/remove is a
more natural bracket. The primitives should be insertedIntoDocument / removedFromDocument and inserted / removed. If you care about whether your
document is rendered, look at its defaultView property. <https://github.com/w3c/webcomponents/issues/286>
2. We think inserted/removed callbacks should be added, for alignment with DOM. <https://github.com/w3c/webcomponents/issues/222>
C. Inheritance for Built-ins
1. We think support for inheritance from built-in elements (other than HTMLElement/SVGElement) should be omitted from a cross-
browser v1. It raises complex implementation issues. <https://github.com/w3c/webcomponents/issues/133 <https://www.w3.org/Bugs/Public/show_bug.cgi?
id=28547>>
D. Syntactic Sugar / Developer Ergonomics
1. We think it would be useful (perhaps post-v1) to make it simpler to create a custom element that is always instantiated with a
shadow DOM from a template. Right now, this common use case requires script and a template in separate places, and a few lines of confusing
79 / 157
Safari
Can I use ? Settingsweb components
4 results found
# Global 67.55%
U.K. 70.69%
IE / Edge Firefox Chrome Safari Opera iOS Safari
*
Opera Mini
* Android
Browser
* Chrome for
Android
8
9
10
11
Edge
31
38
39
40
41
42
31
36
37
39
40
42
43
44
45
46
47
7
7.1
8
9
30
31
32
7.1
8.4
9
8
4.1
4.3
4.4
4.4.4
40 42
HTML templates - LS
Method of declaring a portion of reusable markup that is parsed
but not rendered until cloned.
Current aligned Usage relative Show all
80 / 157
State of Browser Support
All is not Lost
81 / 157
Browsers - with Polyfills
https://github.com/webcomponents/webcomponentsjs#browser-support
82 / 157
Componentised Web Apps Now
83 / 157
Christian Heilmann - July 1st, 2015
‘When we asked the very captive and elite
audience of EdgeConf about Web Components,
nobody raised their hand that they are using them
in real products.
84 / 157
Componentised Web Apps Now -
questions?
Should native browser support stop us thinking about building componentised
web apps?
85 / 157
Componentised Web Apps Now -
questions?
Should native browser support stop us thinking about building componentised
web apps?
No!
86 / 157
Componentised Web Apps Now -
questions?
Should native browser support stop us thinking about building componentised
web apps?
No!
Should we be build componentised web apps anyway?
87 / 157
Componentised Web Apps Now -
questions?
Should native browser support stop us thinking about building componentised
web apps?
No!
Should we be build componentised web apps anyway?
We're already building web apps out of components right now!
88 / 157
JavaScript
Libraries & Frameworks
89 / 157
AngularJS
90 / 157
AngularJS
<script src="js/angular.min.js"></script>
91 / 157
AngularJS
<script src="js/angular.min.js"></script>
<script>
angular.module('demo', [])
.directive('ngAvatar', function () {
return {
92 / 157
AngularJS
<script src="js/angular.min.js"></script>
<script>
angular.module('demo', [])
.directive('ngAvatar', function () {
return {
restrict:"AEC",
93 / 157
AngularJS
<script src="js/angular.min.js"></script>
<script>
angular.module('demo', [])
.directive('ngAvatar', function () {
return {
restrict:"AEC",
scope: {
service: '@',
username: '@'
},
94 / 157
AngularJS
<script src="js/angular.min.js"></script>
<script>
angular.module('demo', [])
.directive('ngAvatar', function () {
return {
restrict:"AEC",
scope: {
service: '@',
username: '@'
},
template: '<img src="http://avatars.io/' +
'{{service}}/{{username}}" />'
};
});
</script>
<body ng-app="demo">
95 / 157
AngularJS
<script src="js/angular.min.js"></script>
<script>
angular.module('demo', [])
.directive('ngAvatar', function () {
return {
restrict:"AEC",
scope: {
service: '@',
username: '@'
},
template: '<img src="http://avatars.io/' +
'{{service}}/{{username}}" />'
};
});
</script>
<body ng-app="demo">
<ng-avatar service="twitter" username="leggetter" />
96 / 157
AngularJS
<script src="js/angular.min.js"></script>
<script>
angular.module('demo', [])
.directive('ngAvatar', function () {
return {
restrict:"AEC",
scope: {
service: '@',
username: '@'
},
template: '<img src="http://avatars.io/' +
'{{service}}/{{username}}" />'
};
});
</script>
<body ng-app="demo">
<ng-avatar service="twitter" username="leggetter" />
97 / 157
EmberJS
98 / 157
EmberJS
<script src="js/jquery-1.10.0.min.js"></script>
99 / 157
EmberJS
<script src="js/jquery-1.10.0.min.js"></script>
<script src="js/handlebars.js"></script>
100 / 157
EmberJS
<script src="js/jquery-1.10.0.min.js"></script>
<script src="js/handlebars.js"></script>
<script src="js/ember.js"></script>
101 / 157
EmberJS
<script src="js/jquery-1.10.0.min.js"></script>
<script src="js/handlebars.js"></script>
<script src="js/ember.js"></script>
<script>
var App = Ember.Application.create();
App.EmAvatarComponent = Ember.Component.extend({
102 / 157
EmberJS
<script src="js/jquery-1.10.0.min.js"></script>
<script src="js/handlebars.js"></script>
<script src="js/ember.js"></script>
<script>
var App = Ember.Application.create();
App.EmAvatarComponent = Ember.Component.extend({
url: function () {
return 'http://avatars.io/' +
this.get( 'service' ) + '/' +
this.get( 'username' );
}.property( 'username' , 'service' )
});
</script>
103 / 157
EmberJS
<script src="js/jquery-1.10.0.min.js"></script>
<script src="js/handlebars.js"></script>
<script src="js/ember.js"></script>
<script>
var App = Ember.Application.create();
App.EmAvatarComponent = Ember.Component.extend({
url: function () {
return 'http://avatars.io/' +
this.get( 'service' ) + '/' +
this.get( 'username' );
}.property( 'username' , 'service' )
});
</script>
<script type="text/x-handlebars" id="components/em-avatar">
<img {{bind-attr src=url}} />
</script>
104 / 157
EmberJS
<script src="js/jquery-1.10.0.min.js"></script>
<script src="js/handlebars.js"></script>
<script src="js/ember.js"></script>
<script>
var App = Ember.Application.create();
App.EmAvatarComponent = Ember.Component.extend({
url: function () {
return 'http://avatars.io/' +
this.get( 'service' ) + '/' +
this.get( 'username' );
}.property( 'username' , 'service' )
});
</script>
<script type="text/x-handlebars" id="components/em-avatar">
<img {{bind-attr src=url}} />
</script>
<script type="text/x-handlebars">
{{em-avatar service="twitter" username="leggetter"}}
</script>
http://jsbin.com/fexawujibe/2/edit?html,output
105 / 157
ReactJS
106 / 157
ReactJS
<script src="js/react.js"></script>
<script src="js/JSXTransformer.js"></script>
107 / 157
ReactJS
<script src="js/react.js"></script>
<script src="js/JSXTransformer.js"></script>
<script type="text/jsx">
var ReAvatar = React.createClass({
render: function() {
return (
<img src={"http://avatars.io/" +
this.props.service + "/" +
this.props.username} />
);
}
});
108 / 157
ReactJS
<script src="js/react.js"></script>
<script src="js/JSXTransformer.js"></script>
<script type="text/jsx">
var ReAvatar = React.createClass({
render: function() {
return (
<img src={"http://avatars.io/" +
this.props.service + "/" +
this.props.username} />
);
}
});
React.render(
<ReAvatar service="twitter" username="leggetter" />,
document.querySelector('re-avatar')
);
</script>
109 / 157
ReactJS
<script src="js/react.js"></script>
<script src="js/JSXTransformer.js"></script>
<script type="text/jsx">
var ReAvatar = React.createClass({
render: function() {
return (
<img src={"http://avatars.io/" +
this.props.service + "/" +
this.props.username} />
);
}
});
React.render(
<ReAvatar service="twitter" username="leggetter" />,
document.querySelector('re-avatar')
);
</script>
<re-avatar />
110 / 157
ReactJS
<script src="js/react.js"></script>
<script src="js/JSXTransformer.js"></script>
<script type="text/jsx">
var ReAvatar = React.createClass({
render: function() {
return (
<img src={"http://avatars.io/" +
this.props.service + "/" +
this.props.username} />
);
}
});
React.render(
<ReAvatar service="twitter" username="leggetter" />,
document.querySelector('re-avatar')
);
</script>
<re-avatar />
111 / 157
112 / 157
Polymer
<script src="webcomponentsjs/webcomponents.min.js"></script>
<link rel="import" href="polymer/polymer.html">
113 / 157
Polymer
<script src="webcomponentsjs/webcomponents.min.js"></script>
<link rel="import" href="polymer/polymer.html">
<polymer-element name="po-avatar" attributes="service username">
114 / 157
Polymer
<script src="webcomponentsjs/webcomponents.min.js"></script>
<link rel="import" href="polymer/polymer.html">
<polymer-element name="po-avatar" attributes="service username">
<template>
<img src="http://avatars.io/{{service}}/{{username}}" />
</template>
115 / 157
Polymer
<script src="webcomponentsjs/webcomponents.min.js"></script>
<link rel="import" href="polymer/polymer.html">
<polymer-element name="po-avatar" attributes="service username">
<template>
<img src="http://avatars.io/{{service}}/{{username}}" />
</template>
<script>
Polymer('po-avatar', {});
</script>
</polymer-element>
116 / 157
Polymer
<script src="webcomponentsjs/webcomponents.min.js"></script>
<link rel="import" href="polymer/polymer.html">
<polymer-element name="po-avatar" attributes="service username">
<template>
<img src="http://avatars.io/{{service}}/{{username}}" />
</template>
<script>
Polymer('po-avatar', {});
</script>
</polymer-element>
<po-avatar service="twitter" username="leggetter" />
117 / 157
Polymer
<script src="webcomponentsjs/webcomponents.min.js"></script>
<link rel="import" href="polymer/polymer.html">
<polymer-element name="po-avatar" attributes="service username">
<template>
<img src="http://avatars.io/{{service}}/{{username}}" />
</template>
<script>
Polymer('po-avatar', {});
</script>
</polymer-element>
<po-avatar service="twitter" username="leggetter" />
118 / 157
Who's using? ...
Angular Directives
119 / 157
Who's using? ...
Angular Directives
Ember Components
120 / 157
Who's using? ...
Angular Directives
Ember Components
React Components
121 / 157
Who's using? ...
Angular Directives
Ember Components
React Components
KnockoutJS Components
122 / 157
Who's using? ...
Angular Directives
Ember Components
React Components
KnockoutJS Components
Vue.js Components
123 / 157
Who's using? ...
Angular Directives
Ember Components
React Components
KnockoutJS Components
Vue.js Components
Backbone Components
124 / 157
Who's using? ...
Angular Directives
Ember Components
React Components
KnockoutJS Components
Vue.js Components
Backbone Components
CanJS Components
125 / 157
Who's using? ...
Angular Directives
Ember Components
React Components
KnockoutJS Components
Vue.js Components
Backbone Components
CanJS Components
Famous Components
126 / 157
Who's using? ...
Angular Directives
Ember Components
React Components
KnockoutJS Components
Vue.js Components
Backbone Components
CanJS Components
Famous Components
Anything.JS Components?
127 / 157
Who's Building Componentised Web Apps now?
Angular, Ember, Backbone, Knockout, React, Vue.js, Web Components with Polyfills, Polymer
...
128 / 157
Who's Building Componentised Web Apps now?
Angular, Ember, Backbone, Knockout, React, Vue.js, Web Components with Polyfills, Polymer
...
You are!
<ng-avatar service="twitter" username="leggetter" />
vs.
<my-avatar service="twitter" username="leggetter" />
129 / 157
Who's Building Componentised Web Apps now?
Angular, Ember, Backbone, Knockout, React, Vue.js, Web Components with Polyfills, Polymer
...
You are!
<ng-avatar service="twitter" username="leggetter" />
vs.
<my-avatar service="twitter" username="leggetter" />
That's the HOW
130 / 157
Why Web Components are the future!
131 / 157
1. You're already building componentised
web apps
If you're not, you probably should be
132 / 157
2. Trends/Alignment
133 / 157
Libraries
Alignment toward Web Components
Angular - Directives
Ember - Components
Knockout - Components
Polymer - build upon Web Components
Angular 2...
134 / 157
http://guides.emberjs.com/v1.13.0/components/
‘Ember's implementation of components hews as
closely to the Web Components specification as
possible. Once Custom Elements are widely
available in browsers, you should be able to easily
migrate your Ember components to the W3C
standard and have them be usable by other
frameworks.
135 / 157
136 / 157
Have a Strategy
Will libraries update to use Web Components?
Align with Web Components to make migrating easier
Split UI rendering and business logic
137 / 157
Browser Vendor Support
Google ✔
Opera ✔
Mozilla ✔
Microsoft ✔
Apple ✔
138 / 157
Dashboard Get Started Design Develop Publish Community WPDev Feedback
Microsoft Edge Developer
Welcome to the Microsoft Edge Developer Suggestion Box!
The Microsoft Edge team is looking for feature requests from the web developer and designer community. Categories
include (but certainly are not limited to) HTML, CSS, JavaScript, Performance, and Developer Tools. If you do not have
a suggestion at this time, you may still cast your vote for the features you would like to see supported!
This feedback will help us with planning and to better understand how web developers and designers are using the
platform. Top standards-based feature requests will also be copied over to http://dev.modern.ie/platform/status/, where
you can track its development status.
Note that this forum is intended for web platform feature suggestions. Related feedback channels:
Microsoft Edge application feedback (or use the Windows Feedback app in Windows Technical Preview)
Microsoft Edge feedback on Windows Phone
For specific bugs, please log an issue on the Connect site
Finally – a few guidelines and notes to keep things running smoothly:
1. Please be sure to search for ideas before entering a new suggestion. This helps to accrue the votes correctly.
2. Please enter a separate suggestion for each idea (avoid entering a suggestion with multiple ideas) and share
some information if possible on the most important scenarios that this enables for you. This helps to keep things
clear as to what people are voting for.
3. The items and rankings on this site are an important input, but do not reflect the final priority list for the Microsoft
Edge engineering team.
4. We will moderate suggestions made in the forum if they do not represent an actual feature request or are
inappropriate.
5. Please do not send any novel or patentable ideas, copyrighted materials, samples or demos which you do not
want to grant a license to Microsoft. See the Terms of Service for more information.
Microsoft Edge Developer
Post a new idea…
All ideas
My feedback
Accessibility  4
CSS  59
Document Object Model (DOM)  7
Extensions  12
F12 Developer Tools  119
Graphics  21
HTML  49
JavaScript  61
Media  14
Miscellaneous  45
Networking  22
Performance  17
Security  1
New and returning users may sign in
Search 139 / 157
3. Demand
4. Encourages good software
development
Component-based Development
140 / 157
Separation of Concerns
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>A new Gmail?</title>
<meta name="description" content="">
</head>
<body>
<header>
<img src="img/logo.png" alt="Google Logo" />
<gmail-search />
<gmail-account-strip />
</header>
<gmail-side-bar>
<nav is="gmail-labels"></nav>
<gmail-contacts />
</gmail-sidebar>
<main>
<nav is="gmail-categories"></nav>
<gmail-email-list />
</main>
<hangouts />
</body>
</html>
141 / 157
Encapsulation
Shadow DOM - Style & DOM encapsulation
Does NOT offer JavaScript protection
Hacky Custom Element
leggetter
twitter
Don't click me!
142 / 157
Loose Coupling
Custom Events
Element API (interface)
Or use existing messaging frameworks
143 / 157
Custom Events
<script>
var CustomEventPrototype = Object.create(HTMLElement.prototype);
CustomEventPrototype.createdCallback = function() {
// Build element ...
this.addEventListener('click', function() {
var customEvent = new CustomEvent('cheese');
this.dispatchEvent(customEvent);
}.bind(this));
};
// ...
144 / 157
Custom Events
<script>
var CustomEventPrototype = Object.create(HTMLElement.prototype);
CustomEventPrototype.createdCallback = function() {
// Build element ...
this.addEventListener('click', function() {
var customEvent = new CustomEvent('cheese');
this.dispatchEvent(customEvent);
}.bind(this));
};
// ...
var customEl = document.getElementById('my_custom_ev');
customEl.addEventListener('cheese', function() {
alert('cheese fired!');
});
</script>
<custom-event-ex id="my_custom_ev"></custom-event-ex>
145 / 157
Element API Attributes & Methods
<script>
CustomEventPrototype.startSpin = function() {
this.img.classList.toggle('spin');
};
CustomEventPrototype.stopSpin = function() {
this.img.classList.toggle('spin');
};
// ...
var spinEl = document.getElementById('spin_el');
spinEl.startSpin();
// ...
spinEl.stopSpin();
</script>
<custom-event-ex id="spin_el"></custom-event-ex>
146 / 157
Supports Change
Encapsulation
Loose Coupling
147 / 157
Encourage Reuse
Ease of Sharing
Composition
<link rel="import" href="https://some-cdn.com/my-avatar.html" />
148 / 157
High Cohesion
myavatar.html
├── js/script.js
├── css/styles.css
└── img/bg.png
149 / 157
Problems? Solved in the future?
HTML Imports
Vulcanize | HTTP2 | JavaScript modules
Shared scripts?
Cache
Multiple versions?
JavaScript scoping in v2
Better cross-component communication?
Allow <link> for CSS in Shadow DOM?
150 / 157
Summary
Custom Elements - Awesome
151 / 157
Summary
Custom Elements - Awesome
HTML Templates, Shadow DOM, HTML Imports
- Native FTW
152 / 157
Summary
Custom Elements - Awesome
HTML Templates, Shadow DOM, HTML Imports
- Native FTW
You can & are building componentised web
apps now - Align
153 / 157
Summary
Custom Elements - Awesome
HTML Templates, Shadow DOM, HTML Imports
- Native FTW
You can & are building componentised web
apps now - Align
Trends & "best practice" ♥ Web Components
154 / 157
Summary
Custom Elements - Awesome
HTML Templates, Shadow DOM, HTML Imports
- Native FTW
You can & are building componentised web
apps now - Align
Trends & "best practice" ♥ Web Components
Web Components are the future!
155 / 157
Resources
http://webcomponents.org/
https://www.polymer-project.org
Wilson Page - The State of Web Components
Christian Heilmann - Web Components are an Endangered Species
Are we compontentized yet (podcast)
Eric Bidelman's Google IO 2014 talk
Angular Material
Google Material Design
HTML Template Chooser
IE UserVoice forum
Source for these slides
http://pusher.com - easily add realtime messaging to your apps
156 / 157
Why you should be using Web Components Now.
And How.
Questions?
leggetter.github.io/web-components-now
PHIL @LEGGETTER
Head of Developer Relations
157 / 157

Contenu connexe

Tendances

SharePoint and jQuery Essentials
SharePoint and jQuery EssentialsSharePoint and jQuery Essentials
SharePoint and jQuery EssentialsMark Rackley
 
Unlock the next era of UI design with Polymer
Unlock the next era of UI design with PolymerUnlock the next era of UI design with Polymer
Unlock the next era of UI design with PolymerRob Dodson
 
jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009Remy Sharp
 
Web Components & Polymer 1.0 (Webinale Berlin)
Web Components & Polymer 1.0 (Webinale Berlin)Web Components & Polymer 1.0 (Webinale Berlin)
Web Components & Polymer 1.0 (Webinale Berlin)Hendrik Ebbers
 
Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017Elyse Kolker Gordon
 
Oracle Application Express & jQuery Mobile - OGh Apex Dag 2012
Oracle Application Express & jQuery Mobile - OGh Apex Dag 2012Oracle Application Express & jQuery Mobile - OGh Apex Dag 2012
Oracle Application Express & jQuery Mobile - OGh Apex Dag 2012crokitta
 
jQuery in the [Aol.] Enterprise
jQuery in the [Aol.] EnterprisejQuery in the [Aol.] Enterprise
jQuery in the [Aol.] EnterpriseDave Artz
 
Simple Web Apps With Sinatra
Simple Web Apps With SinatraSimple Web Apps With Sinatra
Simple Web Apps With Sinatraa_l
 
AtlasCamp 2015: Using add-ons to build add-ons
AtlasCamp 2015: Using add-ons to build add-onsAtlasCamp 2015: Using add-ons to build add-ons
AtlasCamp 2015: Using add-ons to build add-onsAtlassian
 
Angular Directives from Scratch
Angular Directives from ScratchAngular Directives from Scratch
Angular Directives from ScratchChristian Lilley
 
Practical HTML5: Using It Today
Practical HTML5: Using It TodayPractical HTML5: Using It Today
Practical HTML5: Using It TodayDoris Chen
 
Yearning jQuery
Yearning jQueryYearning jQuery
Yearning jQueryRemy Sharp
 
jQuery Anti-Patterns for Performance & Compression
jQuery Anti-Patterns for Performance & CompressionjQuery Anti-Patterns for Performance & Compression
jQuery Anti-Patterns for Performance & CompressionPaul Irish
 
Introduction to javascript templating using handlebars.js
Introduction to javascript templating using handlebars.jsIntroduction to javascript templating using handlebars.js
Introduction to javascript templating using handlebars.jsMindfire Solutions
 
Advanced JQuery Mobile tutorial with Phonegap
Advanced JQuery Mobile tutorial with Phonegap Advanced JQuery Mobile tutorial with Phonegap
Advanced JQuery Mobile tutorial with Phonegap Rakesh Jha
 

Tendances (20)

SharePoint and jQuery Essentials
SharePoint and jQuery EssentialsSharePoint and jQuery Essentials
SharePoint and jQuery Essentials
 
Unlock the next era of UI design with Polymer
Unlock the next era of UI design with PolymerUnlock the next era of UI design with Polymer
Unlock the next era of UI design with Polymer
 
jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009
 
Web Components & Polymer 1.0 (Webinale Berlin)
Web Components & Polymer 1.0 (Webinale Berlin)Web Components & Polymer 1.0 (Webinale Berlin)
Web Components & Polymer 1.0 (Webinale Berlin)
 
Site optimization
Site optimizationSite optimization
Site optimization
 
jQuery Essentials
jQuery EssentialsjQuery Essentials
jQuery Essentials
 
Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017
 
Oracle Application Express & jQuery Mobile - OGh Apex Dag 2012
Oracle Application Express & jQuery Mobile - OGh Apex Dag 2012Oracle Application Express & jQuery Mobile - OGh Apex Dag 2012
Oracle Application Express & jQuery Mobile - OGh Apex Dag 2012
 
jQuery in the [Aol.] Enterprise
jQuery in the [Aol.] EnterprisejQuery in the [Aol.] Enterprise
jQuery in the [Aol.] Enterprise
 
Simple Web Apps With Sinatra
Simple Web Apps With SinatraSimple Web Apps With Sinatra
Simple Web Apps With Sinatra
 
jQuery for beginners
jQuery for beginnersjQuery for beginners
jQuery for beginners
 
AtlasCamp 2015: Using add-ons to build add-ons
AtlasCamp 2015: Using add-ons to build add-onsAtlasCamp 2015: Using add-ons to build add-ons
AtlasCamp 2015: Using add-ons to build add-ons
 
Angular Directives from Scratch
Angular Directives from ScratchAngular Directives from Scratch
Angular Directives from Scratch
 
RequireJS & Handlebars
RequireJS & HandlebarsRequireJS & Handlebars
RequireJS & Handlebars
 
Practical HTML5: Using It Today
Practical HTML5: Using It TodayPractical HTML5: Using It Today
Practical HTML5: Using It Today
 
Yearning jQuery
Yearning jQueryYearning jQuery
Yearning jQuery
 
jQuery Anti-Patterns for Performance & Compression
jQuery Anti-Patterns for Performance & CompressionjQuery Anti-Patterns for Performance & Compression
jQuery Anti-Patterns for Performance & Compression
 
Introduction to javascript templating using handlebars.js
Introduction to javascript templating using handlebars.jsIntroduction to javascript templating using handlebars.js
Introduction to javascript templating using handlebars.js
 
Advanced JQuery Mobile tutorial with Phonegap
Advanced JQuery Mobile tutorial with Phonegap Advanced JQuery Mobile tutorial with Phonegap
Advanced JQuery Mobile tutorial with Phonegap
 
Selenium再入門
Selenium再入門Selenium再入門
Selenium再入門
 

Similaire à Why You Should be Using Web Components Right Now. And How. ForwardJS July 2015

HTML5 New and Improved
HTML5   New and ImprovedHTML5   New and Improved
HTML5 New and ImprovedTimothy Fisher
 
JavaScript DOM - Dynamic interactive Code
JavaScript DOM - Dynamic interactive CodeJavaScript DOM - Dynamic interactive Code
JavaScript DOM - Dynamic interactive CodeLaurence Svekis ✔
 
An Introduction to HTML5
An Introduction to HTML5An Introduction to HTML5
An Introduction to HTML5Steven Chipman
 
#NewMeetup Performance
#NewMeetup Performance#NewMeetup Performance
#NewMeetup PerformanceJustin Cataldo
 
TechDays 2013 Jari Kallonen: What's New WebForms 4.5
TechDays 2013 Jari Kallonen: What's New WebForms 4.5TechDays 2013 Jari Kallonen: What's New WebForms 4.5
TechDays 2013 Jari Kallonen: What's New WebForms 4.5Tieturi Oy
 
Real World Web components
Real World Web componentsReal World Web components
Real World Web componentsJarrod Overson
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2fishwarter
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2fishwarter
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2fishwarter
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2fishwarter
 
The Complementarity of React and Web Components
The Complementarity of React and Web ComponentsThe Complementarity of React and Web Components
The Complementarity of React and Web ComponentsAndrew Rota
 
Polymer - pleasant client-side programming with web components
Polymer - pleasant client-side programming with web componentsPolymer - pleasant client-side programming with web components
Polymer - pleasant client-side programming with web componentspsstoev
 
Geek Moot '09 -- Smarty 101
Geek Moot '09 -- Smarty 101Geek Moot '09 -- Smarty 101
Geek Moot '09 -- Smarty 101Ted Kulp
 
TurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsTurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsAlessandro Molina
 
Web Components v1
Web Components v1Web Components v1
Web Components v1Mike Wilcox
 
关于 Html5 那点事
关于 Html5 那点事关于 Html5 那点事
关于 Html5 那点事Sofish Lin
 
Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4DEVCON
 

Similaire à Why You Should be Using Web Components Right Now. And How. ForwardJS July 2015 (20)

HTML5 New and Improved
HTML5   New and ImprovedHTML5   New and Improved
HTML5 New and Improved
 
JavaScript DOM - Dynamic interactive Code
JavaScript DOM - Dynamic interactive CodeJavaScript DOM - Dynamic interactive Code
JavaScript DOM - Dynamic interactive Code
 
An Introduction to HTML5
An Introduction to HTML5An Introduction to HTML5
An Introduction to HTML5
 
#NewMeetup Performance
#NewMeetup Performance#NewMeetup Performance
#NewMeetup Performance
 
TechDays 2013 Jari Kallonen: What's New WebForms 4.5
TechDays 2013 Jari Kallonen: What's New WebForms 4.5TechDays 2013 Jari Kallonen: What's New WebForms 4.5
TechDays 2013 Jari Kallonen: What's New WebForms 4.5
 
Real World Web components
Real World Web componentsReal World Web components
Real World Web components
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2
 
The Complementarity of React and Web Components
The Complementarity of React and Web ComponentsThe Complementarity of React and Web Components
The Complementarity of React and Web Components
 
Polymer - pleasant client-side programming with web components
Polymer - pleasant client-side programming with web componentsPolymer - pleasant client-side programming with web components
Polymer - pleasant client-side programming with web components
 
Geek Moot '09 -- Smarty 101
Geek Moot '09 -- Smarty 101Geek Moot '09 -- Smarty 101
Geek Moot '09 -- Smarty 101
 
HTML5
HTML5HTML5
HTML5
 
1cst
1cst1cst
1cst
 
TurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsTurboGears2 Pluggable Applications
TurboGears2 Pluggable Applications
 
Web Components v1
Web Components v1Web Components v1
Web Components v1
 
关于 Html5 那点事
关于 Html5 那点事关于 Html5 那点事
关于 Html5 那点事
 
Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4
 
Polymer 1.0
Polymer 1.0Polymer 1.0
Polymer 1.0
 

Plus de Phil Leggetter

An Introduction to AAARRRP: A framework for Defining Your Developer Relations...
An Introduction to AAARRRP: A framework for Defining Your Developer Relations...An Introduction to AAARRRP: A framework for Defining Your Developer Relations...
An Introduction to AAARRRP: A framework for Defining Your Developer Relations...Phil Leggetter
 
How APIs Enable Contextual Communications
How APIs Enable Contextual CommunicationsHow APIs Enable Contextual Communications
How APIs Enable Contextual CommunicationsPhil Leggetter
 
An Introduction to the AAARRRP Developer Relations Strategy Framework and How...
An Introduction to the AAARRRP Developer Relations Strategy Framework and How...An Introduction to the AAARRRP Developer Relations Strategy Framework and How...
An Introduction to the AAARRRP Developer Relations Strategy Framework and How...Phil Leggetter
 
An Introduction to the AAARRRP Developer Relations Strategy Framework and How...
An Introduction to the AAARRRP Developer Relations Strategy Framework and How...An Introduction to the AAARRRP Developer Relations Strategy Framework and How...
An Introduction to the AAARRRP Developer Relations Strategy Framework and How...Phil Leggetter
 
Contextual Communications: What, Why and How? Bristol JS
Contextual Communications: What, Why and How? Bristol JSContextual Communications: What, Why and How? Bristol JS
Contextual Communications: What, Why and How? Bristol JSPhil Leggetter
 
Real-Time Web Apps & .NET. What Are Your Options? NDC Oslo 2016
Real-Time Web Apps & .NET. What Are Your Options? NDC Oslo 2016Real-Time Web Apps & .NET. What Are Your Options? NDC Oslo 2016
Real-Time Web Apps & .NET. What Are Your Options? NDC Oslo 2016Phil Leggetter
 
Real-Time Web Apps & .NET - What are your options?
Real-Time Web Apps & .NET - What are your options?Real-Time Web Apps & .NET - What are your options?
Real-Time Web Apps & .NET - What are your options?Phil Leggetter
 
The Past, Present and Future of Real-Time Apps and Communications
The Past, Present and Future of Real-Time Apps and CommunicationsThe Past, Present and Future of Real-Time Apps and Communications
The Past, Present and Future of Real-Time Apps and CommunicationsPhil Leggetter
 
The Past, Present and Future of Real-Time Apps and Communications
The Past, Present and Future of Real-Time Apps and CommunicationsThe Past, Present and Future of Real-Time Apps and Communications
The Past, Present and Future of Real-Time Apps and CommunicationsPhil Leggetter
 
What's the ROI of Developer Relations?
What's the ROI of Developer Relations?What's the ROI of Developer Relations?
What's the ROI of Developer Relations?Phil Leggetter
 
Real-Time Web Apps & Symfony. What are your options?
Real-Time Web Apps & Symfony. What are your options?Real-Time Web Apps & Symfony. What are your options?
Real-Time Web Apps & Symfony. What are your options?Phil Leggetter
 
Real-Time Web Apps in 2015 & Beyond
Real-Time Web Apps in 2015 & BeyondReal-Time Web Apps in 2015 & Beyond
Real-Time Web Apps in 2015 & BeyondPhil Leggetter
 
Patterns and practices for building enterprise-scale HTML5 apps
Patterns and practices for building enterprise-scale HTML5 appsPatterns and practices for building enterprise-scale HTML5 apps
Patterns and practices for building enterprise-scale HTML5 appsPhil Leggetter
 
Fed London - January 2015
Fed London - January 2015Fed London - January 2015
Fed London - January 2015Phil Leggetter
 
How to Build Single Page HTML5 Apps that Scale
How to Build Single Page HTML5 Apps that ScaleHow to Build Single Page HTML5 Apps that Scale
How to Build Single Page HTML5 Apps that ScalePhil Leggetter
 
Realtime Web Apps in 2014 & Beyond
Realtime Web Apps in 2014 & BeyondRealtime Web Apps in 2014 & Beyond
Realtime Web Apps in 2014 & BeyondPhil Leggetter
 
BladeRunnerJS Show & Tell
BladeRunnerJS Show & TellBladeRunnerJS Show & Tell
BladeRunnerJS Show & TellPhil Leggetter
 
Testing Ginormous JavaScript Apps - ScotlandJS 2014
Testing Ginormous JavaScript Apps - ScotlandJS 2014Testing Ginormous JavaScript Apps - ScotlandJS 2014
Testing Ginormous JavaScript Apps - ScotlandJS 2014Phil Leggetter
 
How to Build Front-End Web Apps that Scale - FutureJS
How to Build Front-End Web Apps that Scale - FutureJSHow to Build Front-End Web Apps that Scale - FutureJS
How to Build Front-End Web Apps that Scale - FutureJSPhil Leggetter
 
Using BladeRunnerJS to Build Front-End Apps that Scale - Fluent 2014
Using BladeRunnerJS to Build Front-End Apps that Scale - Fluent 2014Using BladeRunnerJS to Build Front-End Apps that Scale - Fluent 2014
Using BladeRunnerJS to Build Front-End Apps that Scale - Fluent 2014Phil Leggetter
 

Plus de Phil Leggetter (20)

An Introduction to AAARRRP: A framework for Defining Your Developer Relations...
An Introduction to AAARRRP: A framework for Defining Your Developer Relations...An Introduction to AAARRRP: A framework for Defining Your Developer Relations...
An Introduction to AAARRRP: A framework for Defining Your Developer Relations...
 
How APIs Enable Contextual Communications
How APIs Enable Contextual CommunicationsHow APIs Enable Contextual Communications
How APIs Enable Contextual Communications
 
An Introduction to the AAARRRP Developer Relations Strategy Framework and How...
An Introduction to the AAARRRP Developer Relations Strategy Framework and How...An Introduction to the AAARRRP Developer Relations Strategy Framework and How...
An Introduction to the AAARRRP Developer Relations Strategy Framework and How...
 
An Introduction to the AAARRRP Developer Relations Strategy Framework and How...
An Introduction to the AAARRRP Developer Relations Strategy Framework and How...An Introduction to the AAARRRP Developer Relations Strategy Framework and How...
An Introduction to the AAARRRP Developer Relations Strategy Framework and How...
 
Contextual Communications: What, Why and How? Bristol JS
Contextual Communications: What, Why and How? Bristol JSContextual Communications: What, Why and How? Bristol JS
Contextual Communications: What, Why and How? Bristol JS
 
Real-Time Web Apps & .NET. What Are Your Options? NDC Oslo 2016
Real-Time Web Apps & .NET. What Are Your Options? NDC Oslo 2016Real-Time Web Apps & .NET. What Are Your Options? NDC Oslo 2016
Real-Time Web Apps & .NET. What Are Your Options? NDC Oslo 2016
 
Real-Time Web Apps & .NET - What are your options?
Real-Time Web Apps & .NET - What are your options?Real-Time Web Apps & .NET - What are your options?
Real-Time Web Apps & .NET - What are your options?
 
The Past, Present and Future of Real-Time Apps and Communications
The Past, Present and Future of Real-Time Apps and CommunicationsThe Past, Present and Future of Real-Time Apps and Communications
The Past, Present and Future of Real-Time Apps and Communications
 
The Past, Present and Future of Real-Time Apps and Communications
The Past, Present and Future of Real-Time Apps and CommunicationsThe Past, Present and Future of Real-Time Apps and Communications
The Past, Present and Future of Real-Time Apps and Communications
 
What's the ROI of Developer Relations?
What's the ROI of Developer Relations?What's the ROI of Developer Relations?
What's the ROI of Developer Relations?
 
Real-Time Web Apps & Symfony. What are your options?
Real-Time Web Apps & Symfony. What are your options?Real-Time Web Apps & Symfony. What are your options?
Real-Time Web Apps & Symfony. What are your options?
 
Real-Time Web Apps in 2015 & Beyond
Real-Time Web Apps in 2015 & BeyondReal-Time Web Apps in 2015 & Beyond
Real-Time Web Apps in 2015 & Beyond
 
Patterns and practices for building enterprise-scale HTML5 apps
Patterns and practices for building enterprise-scale HTML5 appsPatterns and practices for building enterprise-scale HTML5 apps
Patterns and practices for building enterprise-scale HTML5 apps
 
Fed London - January 2015
Fed London - January 2015Fed London - January 2015
Fed London - January 2015
 
How to Build Single Page HTML5 Apps that Scale
How to Build Single Page HTML5 Apps that ScaleHow to Build Single Page HTML5 Apps that Scale
How to Build Single Page HTML5 Apps that Scale
 
Realtime Web Apps in 2014 & Beyond
Realtime Web Apps in 2014 & BeyondRealtime Web Apps in 2014 & Beyond
Realtime Web Apps in 2014 & Beyond
 
BladeRunnerJS Show & Tell
BladeRunnerJS Show & TellBladeRunnerJS Show & Tell
BladeRunnerJS Show & Tell
 
Testing Ginormous JavaScript Apps - ScotlandJS 2014
Testing Ginormous JavaScript Apps - ScotlandJS 2014Testing Ginormous JavaScript Apps - ScotlandJS 2014
Testing Ginormous JavaScript Apps - ScotlandJS 2014
 
How to Build Front-End Web Apps that Scale - FutureJS
How to Build Front-End Web Apps that Scale - FutureJSHow to Build Front-End Web Apps that Scale - FutureJS
How to Build Front-End Web Apps that Scale - FutureJS
 
Using BladeRunnerJS to Build Front-End Apps that Scale - Fluent 2014
Using BladeRunnerJS to Build Front-End Apps that Scale - Fluent 2014Using BladeRunnerJS to Build Front-End Apps that Scale - Fluent 2014
Using BladeRunnerJS to Build Front-End Apps that Scale - Fluent 2014
 

Dernier

Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionOnePlan Solutions
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfryanfarris8
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdfPearlKirahMaeRagusta1
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...kalichargn70th171
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip Schwarz
 

Dernier (20)

Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 

Why You Should be Using Web Components Right Now. And How. ForwardJS July 2015

  • 1. Why you should be using Web Components Now. And How. PHIL @LEGGETTER Head of Developer Relations 1 / 157
  • 4. What we'll cover What are Web Components? The State of Web Components Componentised Web Apps Now Why Web Components are the Future! 4 / 157
  • 5. What are Web Components? 5 / 157
  • 6. What are Web Components? Custom Elements HTML Templates Shadow DOM HTML Imports 6 / 157
  • 8. Elements - Structure & Meaning <!doctype html> <html> <head> <meta charset="utf-8" /> <title>HTML Elements</title> <meta name="description" content="" /> <link rel="stylesheet" href="css/stylez.css" /> </head> <body> <nav> <ul> <li><a href="#">Home</a></li> </ul> </nav> <header> <p>Hello world! This (part of) is HTML5 Boilerplate.</p> </header> <main> <article>Ohhhh. Interesting</article> </main> <footer>&copy; me</footer> <script src="js/script.js"></script> </body> </html> 8 / 157
  • 12. <Custom Elements /> Bring semantic markup back More than just markup IMHO the most important part of Web Components 12 / 157
  • 13. Custom Elements: A new Gmail <!doctype html> <html> <head> <meta charset="utf-8"> <title>A new Gmail?</title> <meta name="description" content=""> </head> <body> 13 / 157
  • 14. Custom Elements: A new Gmail <!doctype html> <html> <head> <meta charset="utf-8"> <title>A new Gmail?</title> <meta name="description" content=""> </head> <body> <header> <img src="img/logo.png" alt="Google Logo" /> <gmail-search /> <gmail-account-strip /> </header> 14 / 157
  • 15. Custom Elements: A new Gmail <!doctype html> <html> <head> <meta charset="utf-8"> <title>A new Gmail?</title> <meta name="description" content=""> </head> <body> <header> <img src="img/logo.png" alt="Google Logo" /> <gmail-search /> <gmail-account-strip /> </header> <gmail-side-bar> <nav is="gmail-labels"></nav> <gmail-contacts /> </gmail-sidebar> 15 / 157
  • 16. Custom Elements: A new Gmail <!doctype html> <html> <head> <meta charset="utf-8"> <title>A new Gmail?</title> <meta name="description" content=""> </head> <body> <header> <img src="img/logo.png" alt="Google Logo" /> <gmail-search /> <gmail-account-strip /> </header> <gmail-side-bar> <nav is="gmail-labels"></nav> <gmail-contacts /> </gmail-sidebar> <main> <nav is="gmail-categories"></nav> <gmail-email-list /> </main> 16 / 157
  • 17. Custom Elements: A new Gmail <!doctype html> <html> <head> <meta charset="utf-8"> <title>A new Gmail?</title> <meta name="description" content=""> </head> <body> <header> <img src="img/logo.png" alt="Google Logo" /> <gmail-search /> <gmail-account-strip /> </header> <gmail-side-bar> <nav is="gmail-labels"></nav> <gmail-contacts /> </gmail-sidebar> <main> <nav is="gmail-categories"></nav> <gmail-email-list /> </main> <hangouts /> </body> </html> 17 / 157
  • 18. Tools, Tips & Tricks for building Componentised Web Apps 18 / 157
  • 19. <img src="http://avatars.io/twitter/leggetter" /> <img src="http://avatars.io/instagram/leggetter" /> <img src="http://avatars.io/gravatar/phil@pusher.com" /> <img src="http://api.skype.com/users/pleggetter/profile/avatar" /> Start Simple - An Avatar 19 / 157
  • 20. Custom Elements <my-avatar service="twitter" username="leggetter" /> 20 / 157
  • 21. Custom Elements <my-avatar service="twitter" username="leggetter" /> <script> var MyAvatarPrototype = Object.create(HTMLElement.prototype); 21 / 157
  • 22. Custom Elements <my-avatar service="twitter" username="leggetter" /> <script> var MyAvatarPrototype = Object.create(HTMLElement.prototype); MyAvatarPrototype.createdCallback = function() { var username = this.getAttribute('username'); var service = this.getAttribute('service'); 22 / 157
  • 23. Custom Elements <my-avatar service="twitter" username="leggetter" /> <script> var MyAvatarPrototype = Object.create(HTMLElement.prototype); MyAvatarPrototype.createdCallback = function() { var username = this.getAttribute('username'); var service = this.getAttribute('service'); var url = 'http://avatars.io/' + service + '/' + username; 23 / 157
  • 24. Custom Elements <my-avatar service="twitter" username="leggetter" /> <script> var MyAvatarPrototype = Object.create(HTMLElement.prototype); MyAvatarPrototype.createdCallback = function() { var username = this.getAttribute('username'); var service = this.getAttribute('service'); var url = 'http://avatars.io/' + service + '/' + username; var img = document.createElement( 'img' ); img.setAttribute('src', url); this.appendChild(img); }; 24 / 157
  • 25. Custom Elements <my-avatar service="twitter" username="leggetter" /> <script> var MyAvatarPrototype = Object.create(HTMLElement.prototype); MyAvatarPrototype.createdCallback = function() { var username = this.getAttribute('username'); var service = this.getAttribute('service'); var url = 'http://avatars.io/' + service + '/' + username; var img = document.createElement( 'img' ); img.setAttribute('src', url); this.appendChild(img); }; document.registerElement('my-avatar', { prototype: MyAvatarPrototype }); </script> Define your own elements. 25 / 157
  • 26. <my-avatar service="twitter" username="leggetter" /> <my-avatar service="instagram" username="leggetter" /> <my-avatar service="twitter" username="forwardjs" /> <my-avatar /> 26 / 157
  • 27. Custom Elements - Extending <img is="my-avatar-ext" service="twitter" username="leggetter" /> 27 / 157
  • 28. Custom Elements - Extending <img is="my-avatar-ext" service="twitter" username="leggetter" /> <script> var MyAvatarExtPrototype = Object.create(HTMLImageElement.prototype); 28 / 157
  • 29. Custom Elements - Extending <img is="my-avatar-ext" service="twitter" username="leggetter" /> <script> var MyAvatarExtPrototype = Object.create(HTMLImageElement.prototype); MyAvatarExtPrototype.createdCallback = function() { var username = this.getAttribute('username'), service = this.getAttribute('service'), url = 'http://avatars.io/' + service + '/' + username; this.setAttribute('src', url); }; 29 / 157
  • 30. Custom Elements - Extending <img is="my-avatar-ext" service="twitter" username="leggetter" /> <script> var MyAvatarExtPrototype = Object.create(HTMLImageElement.prototype); MyAvatarExtPrototype.createdCallback = function() { var username = this.getAttribute('username'), service = this.getAttribute('service'), url = 'http://avatars.io/' + service + '/' + username; this.setAttribute('src', url); }; document.registerElement('my-avatar-ext', { prototype: MyAvatarExtPrototype, extends: 'img' }); </script> Extending existing elements 30 / 157
  • 31. Custom Elements - Lifecycle createdCallback attachedCallback detachedCallback attributeChangedCallback(attrName, oldVal, newVal) 31 / 157
  • 32. Create Elements using JavaScript <script> function createPhils() { var tooManyPhils = 104; var phils = 0; do { var el = document.createElement( 'my-avatar' ); el.setAttribute('service', 'twitter'); el.setAttribute('username', 'leggetter'); document.getElementById( 'phils' ).appendChild( el ); ++phils; } while( phils < tooManyPhils ); } </script> Create Phils 32 / 157
  • 36. HTML Templates Create Avatar <template id="my-avatar-template"> <style> .container { background-color: gold; } <!-- omitted for brevity --> </style> <div class="container"> <img class="avatar" /> <span class="username"></span> <span class="service"></span> </div> </template> 36 / 157
  • 37. HTML Templates Create Avatar <template id="my-avatar-template"> <style> .container { background-color: gold; } <!-- omitted for brevity --> </style> <div class="container"> <img class="avatar" /> <span class="username"></span> <span class="service"></span> </div> </template> var MyAvatarTmplPrototype = Object.create(HTMLElement.prototype); MyAvatarTmplPrototype.createdCallback = function() { // get attributes & build url 37 / 157
  • 38. HTML Templates Create Avatar <template id="my-avatar-template"> <style> .container { background-color: gold; } <!-- omitted for brevity --> </style> <div class="container"> <img class="avatar" /> <span class="username"></span> <span class="service"></span> </div> </template> var MyAvatarTmplPrototype = Object.create(HTMLElement.prototype); MyAvatarTmplPrototype.createdCallback = function() { // get attributes & build url var content = document.querySelector( '#my-avatar-template' ).content; var el = document.importNode( content, true ); 38 / 157
  • 39. HTML Templates Create Avatar <template id="my-avatar-template"> <style> .container { background-color: gold; } <!-- omitted for brevity --> </style> <div class="container"> <img class="avatar" /> <span class="username"></span> <span class="service"></span> </div> </template> var MyAvatarTmplPrototype = Object.create(HTMLElement.prototype); MyAvatarTmplPrototype.createdCallback = function() { // get attributes & build url var content = document.querySelector( '#my-avatar-template' ).content; var el = document.importNode( content, true ); el.querySelector( '.avatar' ).setAttribute( 'src', url ); el.querySelector( '.username' ).textContent = username; el.querySelector( '.service' ).textContent = service; this.appendChild( el ); }; 39 / 157
  • 40. HTML Templates Create Avatar <template id="my-avatar-template"> <style> .container { background-color: gold; } <!-- omitted for brevity --> </style> <div class="container"> <img class="avatar" /> <span class="username"></span> <span class="service"></span> </div> </template> var MyAvatarTmplPrototype = Object.create(HTMLElement.prototype); MyAvatarTmplPrototype.createdCallback = function() { // get attributes & build url var content = document.querySelector( '#my-avatar-template' ).content; var el = document.importNode( content, true ); el.querySelector( '.avatar' ).setAttribute( 'src', url ); el.querySelector( '.username' ).textContent = username; el.querySelector( '.service' ).textContent = service; this.appendChild( el ); }; document.registerElement('my-avatar-tmpl', { prototype: MyAvatarTmplPrototype 40 / 157
  • 41. Why native HTML Templates? Libraries → Native Native benefits Document fragment = lightweight Inert until cloned/used 41 / 157
  • 42. Shadow DOM DOM/CSS "scoping" / protection 42 / 157
  • 43. Shadow DOM - Already using it 43 / 157
  • 44. Shadow DOM - Problems it solves 44 / 157
  • 45. Styles <span class="container">Bleed!</span> <template id="my-avatar-tmpl"> <style> .container { background-color: cyan; } ... <my-avatar-tmpl service="twitter" username="leggetter" /> Styles Bleed! Create Shadow DOM - Problems it solves 45 / 157
  • 46. Styles <span class="container">Bleed!</span> <template id="my-avatar-tmpl"> <style> .container { background-color: cyan; } ... <my-avatar-tmpl service="twitter" username="leggetter" /> Styles Bleed! Create <template id="my-avatar-template"> <div class="container"> <img id="avatar" /> ... </template> Global DOM e.g. id attributes Shadow DOM - Problems it solves 46 / 157
  • 47. Shadow DOM - In Action Create ForwardJS 47 / 157
  • 48. Shadow DOM - In Action Create ForwardJS <template id="my-avatar-shadow-tmpl"> <style> .container { background-color: red; color: white; } ... </style> <div class="container"> <img id="avatar" /> ... </div> </template> 48 / 157
  • 49. Shadow DOM - In Action Create ForwardJS <template id="my-avatar-shadow-tmpl"> <style> .container { background-color: red; color: white; } ... </style> <div class="container"> <img id="avatar" /> ... </div> </template> var MyAvatarShadowPrototype = Object.create(HTMLElement.prototype); MyAvatarShadowPrototype.createdCallback = function() { // get attributes & build url var content = document.querySelector( '#my-avatar-shadow-tmpl' ).content; 49 / 157
  • 50. Shadow DOM - In Action Create ForwardJS <template id="my-avatar-shadow-tmpl"> <style> .container { background-color: red; color: white; } ... </style> <div class="container"> <img id="avatar" /> ... </div> </template> var MyAvatarShadowPrototype = Object.create(HTMLElement.prototype); MyAvatarShadowPrototype.createdCallback = function() { // get attributes & build url var content = document.querySelector( '#my-avatar-shadow-tmpl' ).content; this.shadow = this.createShadowRoot(); this.shadow.appendChild( document.importNode( content, true ) ); 50 / 157
  • 51. Shadow DOM - In Action Create ForwardJS <template id="my-avatar-shadow-tmpl"> <style> .container { background-color: red; color: white; } ... </style> <div class="container"> <img id="avatar" /> ... </div> </template> var MyAvatarShadowPrototype = Object.create(HTMLElement.prototype); MyAvatarShadowPrototype.createdCallback = function() { // get attributes & build url var content = document.querySelector( '#my-avatar-shadow-tmpl' ).content; this.shadow = this.createShadowRoot(); this.shadow.appendChild( document.importNode( content, true ) ); this.shadow.querySelector( '#avatar' ).setAttribute( 'src', url ); this.shadow.querySelector( '#username' ).textContent = username; this.shadow.querySelector( '#service' ).textContent = service; }; 51 / 157
  • 52. Shadow DOM - In Action Create ForwardJS <template id="my-avatar-shadow-tmpl"> <style> .container { background-color: red; color: white; } ... </style> <div class="container"> <img id="avatar" /> ... </div> </template> var MyAvatarShadowPrototype = Object.create(HTMLElement.prototype); MyAvatarShadowPrototype.createdCallback = function() { // get attributes & build url var content = document.querySelector( '#my-avatar-shadow-tmpl' ).content; this.shadow = this.createShadowRoot(); this.shadow.appendChild( document.importNode( content, true ) ); this.shadow.querySelector( '#avatar' ).setAttribute( 'src', url ); this.shadow.querySelector( '#username' ).textContent = username; this.shadow.querySelector( '#service' ).textContent = service; }; document.registerElement('my-avatar-shadow', { prototype: MyAvatarShadowPrototype 52 / 157
  • 53. Why Shadow DOM? DOM & CSS Scoping Protection for all: Page and Element Encapsulation 53 / 157
  • 54. HTML Imports Loading & Dependency Management 54 / 157
  • 55. HTML Imports - Example Before <link rel="stylesheet" href="bootstrap.css" /> <link rel="stylesheet" href="fonts.css" /> <script src="jquery.js"></script> <script src="bootstrap.js"></script> <script src="bootstrap-tooltip.js"></script> <script src="bootstrap-dropdown.js"></script> 55 / 157
  • 56. HTML Imports - Example Before <link rel="stylesheet" href="bootstrap.css" /> <link rel="stylesheet" href="fonts.css" /> <script src="jquery.js"></script> <script src="bootstrap.js"></script> <script src="bootstrap-tooltip.js"></script> <script src="bootstrap-dropdown.js"></script> After <link rel="import" href="bootstrap.html" /> 56 / 157
  • 57. HTML Imports - Composition team-pusher.html 57 / 157
  • 58. HTML Imports - Composition team-pusher.html <link rel="import" href="my-avatar-import.html" /> 58 / 157
  • 59. HTML Imports - Composition team-pusher.html <link rel="import" href="my-avatar-import.html" /> <template id="team-pusher-tmpl"> <style> </style> <my-avatar-import service="twitter" username="maxthelion" /> <my-avatar-import service="twitter" username="copypastaa" /> ... <my-avatar-import service="twitter" username="leggetter" /> </template> ... 59 / 157
  • 60. HTML Imports - Composition team-pusher.html <link rel="import" href="my-avatar-import.html" /> <template id="team-pusher-tmpl"> <style> </style> <my-avatar-import service="twitter" username="maxthelion" /> <my-avatar-import service="twitter" username="copypastaa" /> ... <my-avatar-import service="twitter" username="leggetter" /> </template> <script> var TeamPusherPrototype = Object.create(HTMLElement.prototype); TeamPusherPrototype.createdCallback = function() { // Get template, createShadowRoot etc. }; document.registerElement('team-pusher', { prototype: TeamPusherPrototype }); </script> ... 60 / 157
  • 61. HTML Imports - Composition Demo <link rel="import" href="assets/team-pusher.html" /> <team-pusher></team-pusher> 61 / 157
  • 62. HTML Imports - Composition Demo <link rel="import" href="assets/team-pusher.html" /> <team-pusher></team-pusher> maxthelion twitter copypastaa twitter zimbatm twitter loicdumas twitter mdpye twitter olga_dukova twitter pawel_ledwon twitter hamchapman twitter LaurieWang_ twitter swstagg twitter vivangkumar twitter willsewell_ twitter davidrbiggs twitter leggetter twitter We're Hiring! pusher.com/jobs 62 / 157
  • 63. Why Use HTML Imports? Bundle JS/HTML/CSS → single URL Basic dependency management Sharing, Reuse, Composition 63 / 157
  • 65. Get & use document from the currentScript ( function( currentScript ) { var importDoc = currentScript.ownerDocument; TeamPusherPrototype.createdCallback = function() { var content = importDoc.querySelector( '#team-pusher-tmpl' ).content; // ... }; } )( document._currentScript || document.currentScript ); 65 / 157
  • 66. importNode and NOT cloneNode for Template // Note: use ownerDoc var content = ownerDoc.querySelector( '#my-template' ); var clone = ownerDoc.importNode( content, true ); 66 / 157
  • 67. You can't <link> into the Shadow DOM <template> <link rel="stylesheet" href="path/to/style.css" /> </template> 67 / 157
  • 69. The State of Custom Elements is Concerns around Accessibility Point of Upgrade When HTMLElement is transformed into Custom Element 69 / 157
  • 70. The State of Templates ✔ 70 / 157
  • 71. The State of Shadow DOM <content select="tag" /> Declarative element content placement 71 / 157
  • 72. The State of Shadow DOM <content select="tag" /> Declarative element content placement element.createShadowRoot({ mode: 'closed' }); protecting shadowRoot 72 / 157
  • 73. The State of Shadow DOM <content select="tag" /> Declarative element content placement element.createShadowRoot({ mode: 'closed' }); protecting shadowRoot .foo >>> div { color: red } Shadow piercing combinators ... 73 / 157
  • 74. The State of HTML Imports 74 / 157
  • 75. Firefox https://hacks.mozilla.org/2014/12/mozilla-and-web-components/ “Mozilla will not ship an implementation of HTML Imports. We expect that once JavaScript modules ... is shipped, the way we look at this problem will have changed. 75 / 157
  • 76. Essential "State of" Reading Wilson Page - The State of Web Components Microsoft Edge Team - Bringing componentization to the web: An overview of Web Components 76 / 157
  • 77. The State of Browsers 77 / 157
  • 79. Apple's updated feedback on Custom Elements and Shadow DOM From: Maciej Stachowiak <mjs@apple.com> Date: Mon, 20 Jul 2015 18:17:24 -0700 Message-id: <E9841AA1-9255-4324-946E-E785B15DAE93@apple.com> To: public-webapps <public-webapps@w3.org> A while back we sent a consolidated pile of feedback on the Web Components family of specs. In preparation for tomorrow's F2F, here is an update on our positions. We've also changed the bugzilla links to point to relevant github issues instead. We're only covering Custom Elements (the main expected topic), and also Shadow DOM (in case that gets discussed too). I. ==== Custom Elements ==== A. ES6 classes / Upgrade / Synchronous Constructors 1. In general, we support the "synchronous constructors" approach to the "prototype swizzling" approach, as the lesser evil. While tricky to implement correctly, it makes a lot more sense and fits more naturally into the language. We are willing to do the work to make it feasible. 2. Custom elements should support initialization using an ES6 class constructo instead of a separate callback. <https://github.com/w3c/webcomponents/issues/139 <https://www.w3.org/Bugs/Public/show_bug.cgi?id=28541>> 3. We don’t think upgrading should be supported. The tradeoffs of different options have been much-discussed. <https://github.com/w3c/webcomponents/issues/134 <https://www.w3.org/Bugs/Public/show_bug.cgi?id=28544>> 4. Specifically, we don't really like the "Optional Upgrades, Optional Constructors" proposal (seems like it's the worst of both worlds in terms of complexity and weirdness) or the "Parser-Created Classes" proposal (not clear how this even solves the problem). B. Insertion/Removal Callbacks 1. We think the current attached/detached callbacks should be removed. They don’t match core DOM concepts and insert/remove is a more natural bracket. The primitives should be insertedIntoDocument / removedFromDocument and inserted / removed. If you care about whether your document is rendered, look at its defaultView property. <https://github.com/w3c/webcomponents/issues/286> 2. We think inserted/removed callbacks should be added, for alignment with DOM. <https://github.com/w3c/webcomponents/issues/222> C. Inheritance for Built-ins 1. We think support for inheritance from built-in elements (other than HTMLElement/SVGElement) should be omitted from a cross- browser v1. It raises complex implementation issues. <https://github.com/w3c/webcomponents/issues/133 <https://www.w3.org/Bugs/Public/show_bug.cgi? id=28547>> D. Syntactic Sugar / Developer Ergonomics 1. We think it would be useful (perhaps post-v1) to make it simpler to create a custom element that is always instantiated with a shadow DOM from a template. Right now, this common use case requires script and a template in separate places, and a few lines of confusing 79 / 157 Safari
  • 80. Can I use ? Settingsweb components 4 results found # Global 67.55% U.K. 70.69% IE / Edge Firefox Chrome Safari Opera iOS Safari * Opera Mini * Android Browser * Chrome for Android 8 9 10 11 Edge 31 38 39 40 41 42 31 36 37 39 40 42 43 44 45 46 47 7 7.1 8 9 30 31 32 7.1 8.4 9 8 4.1 4.3 4.4 4.4.4 40 42 HTML templates - LS Method of declaring a portion of reusable markup that is parsed but not rendered until cloned. Current aligned Usage relative Show all 80 / 157 State of Browser Support
  • 81. All is not Lost 81 / 157
  • 82. Browsers - with Polyfills https://github.com/webcomponents/webcomponentsjs#browser-support 82 / 157
  • 83. Componentised Web Apps Now 83 / 157
  • 84. Christian Heilmann - July 1st, 2015 ‘When we asked the very captive and elite audience of EdgeConf about Web Components, nobody raised their hand that they are using them in real products. 84 / 157
  • 85. Componentised Web Apps Now - questions? Should native browser support stop us thinking about building componentised web apps? 85 / 157
  • 86. Componentised Web Apps Now - questions? Should native browser support stop us thinking about building componentised web apps? No! 86 / 157
  • 87. Componentised Web Apps Now - questions? Should native browser support stop us thinking about building componentised web apps? No! Should we be build componentised web apps anyway? 87 / 157
  • 88. Componentised Web Apps Now - questions? Should native browser support stop us thinking about building componentised web apps? No! Should we be build componentised web apps anyway? We're already building web apps out of components right now! 88 / 157
  • 94. AngularJS <script src="js/angular.min.js"></script> <script> angular.module('demo', []) .directive('ngAvatar', function () { return { restrict:"AEC", scope: { service: '@', username: '@' }, 94 / 157
  • 95. AngularJS <script src="js/angular.min.js"></script> <script> angular.module('demo', []) .directive('ngAvatar', function () { return { restrict:"AEC", scope: { service: '@', username: '@' }, template: '<img src="http://avatars.io/' + '{{service}}/{{username}}" />' }; }); </script> <body ng-app="demo"> 95 / 157
  • 96. AngularJS <script src="js/angular.min.js"></script> <script> angular.module('demo', []) .directive('ngAvatar', function () { return { restrict:"AEC", scope: { service: '@', username: '@' }, template: '<img src="http://avatars.io/' + '{{service}}/{{username}}" />' }; }); </script> <body ng-app="demo"> <ng-avatar service="twitter" username="leggetter" /> 96 / 157
  • 97. AngularJS <script src="js/angular.min.js"></script> <script> angular.module('demo', []) .directive('ngAvatar', function () { return { restrict:"AEC", scope: { service: '@', username: '@' }, template: '<img src="http://avatars.io/' + '{{service}}/{{username}}" />' }; }); </script> <body ng-app="demo"> <ng-avatar service="twitter" username="leggetter" /> 97 / 157
  • 102. EmberJS <script src="js/jquery-1.10.0.min.js"></script> <script src="js/handlebars.js"></script> <script src="js/ember.js"></script> <script> var App = Ember.Application.create(); App.EmAvatarComponent = Ember.Component.extend({ 102 / 157
  • 103. EmberJS <script src="js/jquery-1.10.0.min.js"></script> <script src="js/handlebars.js"></script> <script src="js/ember.js"></script> <script> var App = Ember.Application.create(); App.EmAvatarComponent = Ember.Component.extend({ url: function () { return 'http://avatars.io/' + this.get( 'service' ) + '/' + this.get( 'username' ); }.property( 'username' , 'service' ) }); </script> 103 / 157
  • 104. EmberJS <script src="js/jquery-1.10.0.min.js"></script> <script src="js/handlebars.js"></script> <script src="js/ember.js"></script> <script> var App = Ember.Application.create(); App.EmAvatarComponent = Ember.Component.extend({ url: function () { return 'http://avatars.io/' + this.get( 'service' ) + '/' + this.get( 'username' ); }.property( 'username' , 'service' ) }); </script> <script type="text/x-handlebars" id="components/em-avatar"> <img {{bind-attr src=url}} /> </script> 104 / 157
  • 105. EmberJS <script src="js/jquery-1.10.0.min.js"></script> <script src="js/handlebars.js"></script> <script src="js/ember.js"></script> <script> var App = Ember.Application.create(); App.EmAvatarComponent = Ember.Component.extend({ url: function () { return 'http://avatars.io/' + this.get( 'service' ) + '/' + this.get( 'username' ); }.property( 'username' , 'service' ) }); </script> <script type="text/x-handlebars" id="components/em-avatar"> <img {{bind-attr src=url}} /> </script> <script type="text/x-handlebars"> {{em-avatar service="twitter" username="leggetter"}} </script> http://jsbin.com/fexawujibe/2/edit?html,output 105 / 157
  • 108. ReactJS <script src="js/react.js"></script> <script src="js/JSXTransformer.js"></script> <script type="text/jsx"> var ReAvatar = React.createClass({ render: function() { return ( <img src={"http://avatars.io/" + this.props.service + "/" + this.props.username} /> ); } }); 108 / 157
  • 109. ReactJS <script src="js/react.js"></script> <script src="js/JSXTransformer.js"></script> <script type="text/jsx"> var ReAvatar = React.createClass({ render: function() { return ( <img src={"http://avatars.io/" + this.props.service + "/" + this.props.username} /> ); } }); React.render( <ReAvatar service="twitter" username="leggetter" />, document.querySelector('re-avatar') ); </script> 109 / 157
  • 110. ReactJS <script src="js/react.js"></script> <script src="js/JSXTransformer.js"></script> <script type="text/jsx"> var ReAvatar = React.createClass({ render: function() { return ( <img src={"http://avatars.io/" + this.props.service + "/" + this.props.username} /> ); } }); React.render( <ReAvatar service="twitter" username="leggetter" />, document.querySelector('re-avatar') ); </script> <re-avatar /> 110 / 157
  • 111. ReactJS <script src="js/react.js"></script> <script src="js/JSXTransformer.js"></script> <script type="text/jsx"> var ReAvatar = React.createClass({ render: function() { return ( <img src={"http://avatars.io/" + this.props.service + "/" + this.props.username} /> ); } }); React.render( <ReAvatar service="twitter" username="leggetter" />, document.querySelector('re-avatar') ); </script> <re-avatar /> 111 / 157
  • 114. Polymer <script src="webcomponentsjs/webcomponents.min.js"></script> <link rel="import" href="polymer/polymer.html"> <polymer-element name="po-avatar" attributes="service username"> 114 / 157
  • 115. Polymer <script src="webcomponentsjs/webcomponents.min.js"></script> <link rel="import" href="polymer/polymer.html"> <polymer-element name="po-avatar" attributes="service username"> <template> <img src="http://avatars.io/{{service}}/{{username}}" /> </template> 115 / 157
  • 116. Polymer <script src="webcomponentsjs/webcomponents.min.js"></script> <link rel="import" href="polymer/polymer.html"> <polymer-element name="po-avatar" attributes="service username"> <template> <img src="http://avatars.io/{{service}}/{{username}}" /> </template> <script> Polymer('po-avatar', {}); </script> </polymer-element> 116 / 157
  • 117. Polymer <script src="webcomponentsjs/webcomponents.min.js"></script> <link rel="import" href="polymer/polymer.html"> <polymer-element name="po-avatar" attributes="service username"> <template> <img src="http://avatars.io/{{service}}/{{username}}" /> </template> <script> Polymer('po-avatar', {}); </script> </polymer-element> <po-avatar service="twitter" username="leggetter" /> 117 / 157
  • 118. Polymer <script src="webcomponentsjs/webcomponents.min.js"></script> <link rel="import" href="polymer/polymer.html"> <polymer-element name="po-avatar" attributes="service username"> <template> <img src="http://avatars.io/{{service}}/{{username}}" /> </template> <script> Polymer('po-avatar', {}); </script> </polymer-element> <po-avatar service="twitter" username="leggetter" /> 118 / 157
  • 119. Who's using? ... Angular Directives 119 / 157
  • 120. Who's using? ... Angular Directives Ember Components 120 / 157
  • 121. Who's using? ... Angular Directives Ember Components React Components 121 / 157
  • 122. Who's using? ... Angular Directives Ember Components React Components KnockoutJS Components 122 / 157
  • 123. Who's using? ... Angular Directives Ember Components React Components KnockoutJS Components Vue.js Components 123 / 157
  • 124. Who's using? ... Angular Directives Ember Components React Components KnockoutJS Components Vue.js Components Backbone Components 124 / 157
  • 125. Who's using? ... Angular Directives Ember Components React Components KnockoutJS Components Vue.js Components Backbone Components CanJS Components 125 / 157
  • 126. Who's using? ... Angular Directives Ember Components React Components KnockoutJS Components Vue.js Components Backbone Components CanJS Components Famous Components 126 / 157
  • 127. Who's using? ... Angular Directives Ember Components React Components KnockoutJS Components Vue.js Components Backbone Components CanJS Components Famous Components Anything.JS Components? 127 / 157
  • 128. Who's Building Componentised Web Apps now? Angular, Ember, Backbone, Knockout, React, Vue.js, Web Components with Polyfills, Polymer ... 128 / 157
  • 129. Who's Building Componentised Web Apps now? Angular, Ember, Backbone, Knockout, React, Vue.js, Web Components with Polyfills, Polymer ... You are! <ng-avatar service="twitter" username="leggetter" /> vs. <my-avatar service="twitter" username="leggetter" /> 129 / 157
  • 130. Who's Building Componentised Web Apps now? Angular, Ember, Backbone, Knockout, React, Vue.js, Web Components with Polyfills, Polymer ... You are! <ng-avatar service="twitter" username="leggetter" /> vs. <my-avatar service="twitter" username="leggetter" /> That's the HOW 130 / 157
  • 131. Why Web Components are the future! 131 / 157
  • 132. 1. You're already building componentised web apps If you're not, you probably should be 132 / 157
  • 134. Libraries Alignment toward Web Components Angular - Directives Ember - Components Knockout - Components Polymer - build upon Web Components Angular 2... 134 / 157
  • 135. http://guides.emberjs.com/v1.13.0/components/ ‘Ember's implementation of components hews as closely to the Web Components specification as possible. Once Custom Elements are widely available in browsers, you should be able to easily migrate your Ember components to the W3C standard and have them be usable by other frameworks. 135 / 157
  • 137. Have a Strategy Will libraries update to use Web Components? Align with Web Components to make migrating easier Split UI rendering and business logic 137 / 157
  • 138. Browser Vendor Support Google ✔ Opera ✔ Mozilla ✔ Microsoft ✔ Apple ✔ 138 / 157
  • 139. Dashboard Get Started Design Develop Publish Community WPDev Feedback Microsoft Edge Developer Welcome to the Microsoft Edge Developer Suggestion Box! The Microsoft Edge team is looking for feature requests from the web developer and designer community. Categories include (but certainly are not limited to) HTML, CSS, JavaScript, Performance, and Developer Tools. If you do not have a suggestion at this time, you may still cast your vote for the features you would like to see supported! This feedback will help us with planning and to better understand how web developers and designers are using the platform. Top standards-based feature requests will also be copied over to http://dev.modern.ie/platform/status/, where you can track its development status. Note that this forum is intended for web platform feature suggestions. Related feedback channels: Microsoft Edge application feedback (or use the Windows Feedback app in Windows Technical Preview) Microsoft Edge feedback on Windows Phone For specific bugs, please log an issue on the Connect site Finally – a few guidelines and notes to keep things running smoothly: 1. Please be sure to search for ideas before entering a new suggestion. This helps to accrue the votes correctly. 2. Please enter a separate suggestion for each idea (avoid entering a suggestion with multiple ideas) and share some information if possible on the most important scenarios that this enables for you. This helps to keep things clear as to what people are voting for. 3. The items and rankings on this site are an important input, but do not reflect the final priority list for the Microsoft Edge engineering team. 4. We will moderate suggestions made in the forum if they do not represent an actual feature request or are inappropriate. 5. Please do not send any novel or patentable ideas, copyrighted materials, samples or demos which you do not want to grant a license to Microsoft. See the Terms of Service for more information. Microsoft Edge Developer Post a new idea… All ideas My feedback Accessibility  4 CSS  59 Document Object Model (DOM)  7 Extensions  12 F12 Developer Tools  119 Graphics  21 HTML  49 JavaScript  61 Media  14 Miscellaneous  45 Networking  22 Performance  17 Security  1 New and returning users may sign in Search 139 / 157 3. Demand
  • 140. 4. Encourages good software development Component-based Development 140 / 157
  • 141. Separation of Concerns <!doctype html> <html> <head> <meta charset="utf-8"> <title>A new Gmail?</title> <meta name="description" content=""> </head> <body> <header> <img src="img/logo.png" alt="Google Logo" /> <gmail-search /> <gmail-account-strip /> </header> <gmail-side-bar> <nav is="gmail-labels"></nav> <gmail-contacts /> </gmail-sidebar> <main> <nav is="gmail-categories"></nav> <gmail-email-list /> </main> <hangouts /> </body> </html> 141 / 157
  • 142. Encapsulation Shadow DOM - Style & DOM encapsulation Does NOT offer JavaScript protection Hacky Custom Element leggetter twitter Don't click me! 142 / 157
  • 143. Loose Coupling Custom Events Element API (interface) Or use existing messaging frameworks 143 / 157
  • 144. Custom Events <script> var CustomEventPrototype = Object.create(HTMLElement.prototype); CustomEventPrototype.createdCallback = function() { // Build element ... this.addEventListener('click', function() { var customEvent = new CustomEvent('cheese'); this.dispatchEvent(customEvent); }.bind(this)); }; // ... 144 / 157
  • 145. Custom Events <script> var CustomEventPrototype = Object.create(HTMLElement.prototype); CustomEventPrototype.createdCallback = function() { // Build element ... this.addEventListener('click', function() { var customEvent = new CustomEvent('cheese'); this.dispatchEvent(customEvent); }.bind(this)); }; // ... var customEl = document.getElementById('my_custom_ev'); customEl.addEventListener('cheese', function() { alert('cheese fired!'); }); </script> <custom-event-ex id="my_custom_ev"></custom-event-ex> 145 / 157
  • 146. Element API Attributes & Methods <script> CustomEventPrototype.startSpin = function() { this.img.classList.toggle('spin'); }; CustomEventPrototype.stopSpin = function() { this.img.classList.toggle('spin'); }; // ... var spinEl = document.getElementById('spin_el'); spinEl.startSpin(); // ... spinEl.stopSpin(); </script> <custom-event-ex id="spin_el"></custom-event-ex> 146 / 157
  • 148. Encourage Reuse Ease of Sharing Composition <link rel="import" href="https://some-cdn.com/my-avatar.html" /> 148 / 157
  • 149. High Cohesion myavatar.html ├── js/script.js ├── css/styles.css └── img/bg.png 149 / 157
  • 150. Problems? Solved in the future? HTML Imports Vulcanize | HTTP2 | JavaScript modules Shared scripts? Cache Multiple versions? JavaScript scoping in v2 Better cross-component communication? Allow <link> for CSS in Shadow DOM? 150 / 157
  • 151. Summary Custom Elements - Awesome 151 / 157
  • 152. Summary Custom Elements - Awesome HTML Templates, Shadow DOM, HTML Imports - Native FTW 152 / 157
  • 153. Summary Custom Elements - Awesome HTML Templates, Shadow DOM, HTML Imports - Native FTW You can & are building componentised web apps now - Align 153 / 157
  • 154. Summary Custom Elements - Awesome HTML Templates, Shadow DOM, HTML Imports - Native FTW You can & are building componentised web apps now - Align Trends & "best practice" ♥ Web Components 154 / 157
  • 155. Summary Custom Elements - Awesome HTML Templates, Shadow DOM, HTML Imports - Native FTW You can & are building componentised web apps now - Align Trends & "best practice" ♥ Web Components Web Components are the future! 155 / 157
  • 156. Resources http://webcomponents.org/ https://www.polymer-project.org Wilson Page - The State of Web Components Christian Heilmann - Web Components are an Endangered Species Are we compontentized yet (podcast) Eric Bidelman's Google IO 2014 talk Angular Material Google Material Design HTML Template Chooser IE UserVoice forum Source for these slides http://pusher.com - easily add realtime messaging to your apps 156 / 157
  • 157. Why you should be using Web Components Now. And How. Questions? leggetter.github.io/web-components-now PHIL @LEGGETTER Head of Developer Relations 157 / 157