Web Components 2016 & Polymer v2

2016.10.09 DevFest Tokyo 2016

Web Components 2016 & Polymer v2 by @1000ch

@1000ch

Web アプリケーション開発を専門とするソフトウェアエンジニア。企業で働く傍ら、技術顧問として複数企業のエンジニアリングに関わり、高品質で維持しやすい Web アプリケーションを作るための活動を続けている。

Web Components 2016 & Polymer v2 by @1000ch

アジェンダ

  • Web Components おさらい
  • 最近の Web Components 事情
  • Polymer v2 is coming!!
Web Components 2016 & Polymer v2 by @1000ch

 Web Components のおさらい

Web Components 2016 & Polymer v2 by @1000ch

「Web におけるコンポーネント」の難しさ

長らく Web 開発者が向き合ってきた

Web Components 2016 & Polymer v2 by @1000ch

再利用可能な Web のコンポーネント

  • それを 作る難しさ使うコスト
  • 特定のライブラリへの依存問題
  • エコシステムが醸成されない問題
  • 容赦なくグローバルを汚染する問題
Web Components 2016 & Polymer v2 by @1000ch

CSS だけはどうにもならない

CSS はつらい。本当につらい。

Web Components 2016 & Polymer v2 by @1000ch

Web 標準技術を組み合わせて実現する(重要)

  • アプローチはどれも特定のツールや手法に依存してきた
  • Web のコンポーネント を作る手法が一般化される
  • 「そうだ、 Extensible Web だ」
Web Components 2016 & Polymer v2 by @1000ch

Web Components を支える技術

Web Components 2016 & Polymer v2 by @1000ch

最近の Web Components 事情

Web Components 2016 & Polymer v2 by @1000ch

Shadow DOM v1 と Custom Elements v1

これまでのものを v0、新たなものを v1 として、改めて仕様の策定が進んでいる

Web Components 2016 & Polymer v2 by @1000ch

Shadow DOM v1

Web Components 2016 & Polymer v2 by @1000ch

createShadowRoot() から attachShadow()

const div = document.querySelector('div');
const shadowRoot = div.attachShadow({
  mode: 'open' // or 'close'
});

// readonly な shadowRoot プロパティの追加
console.log(div.shadowRoot);

引数に open か close かどうかを指定する(必須)

Web Components 2016 & Polymer v2 by @1000ch

Opened Shadow DOM と Closed Shadow DOM

外部からアクセスできる Shadow DOM と、アクセスできない Shadow DOM。 Closed Shadow DOM であれば shadowRoot プロパティは null を返す

Web Components 2016 & Polymer v2 by @1000ch

複数 Shadow Root の廃止

Though multiple shadow roots were originally introduced to support an Inheritance Model for components, Blink has already deprecated this feature even in v0. Do not use multiple shadow roots.

ある要素の attachShadow() を2回以上実行すると例外が発生する

Web Components 2016 & Polymer v2 by @1000ch

制限された Shadow Host になれる要素

article, aside, blockquote, body, div, footer, h1, h2, h3, h4, h5, h6, header, nav, p, section, span

Web Components 2016 & Polymer v2 by @1000ch

<content> から <slot>

<content> で指定していた Insertion Points は、 <slot> に代わり Slots と表現されるようになる。セレクタで指定していたのが、 <slot name=slot-name> のようなスロット名の完全一致で挿入される

Web Components 2016 & Polymer v2 by @1000ch

<content による挿入から

<template>
  <style>
    ::content input { background: skyblue; }
  </style>
  <div>
    <content select=".class-name"></content>
    <content></content>
  </div>
</template>

<form-container>
  <input class="class-name" type="text">
  <button>Button</button>
</form-container>
Web Components 2016 & Polymer v2 by @1000ch

<slot> による挿入へ

<template>
  <style>
    ::slotted(input) { background: skyblue; }
  </style>
  <div>
    <slot name="slot-name"></slot>
    <slot></slot>
  </div>
</template>

<form-container>
  <input slot="slot-name" type="text">
  <button>Button</button>
</form-container>
Web Components 2016 & Polymer v2 by @1000ch

What's New in Shadow DOM v1 (by examples)

更なる詳細はこちらの資料を参照のこと

Web Components 2016 & Polymer v2 by @1000ch

Custom Elements v1

  • ES2015 class ベースの要素定義
  • ライフサイクルコールバックの見直し
  • document.registerElement から window.customElements
Web Components 2016 & Polymer v2 by @1000ch

Custom Elements v0

<script>
  const FooElement = Object.create(HTMLElement.prototype);
  FooElement.createdCallback = () => { ... };
  FooElement.attachedCallback = () => { ... };
  FooElement.detachedCallback = () => { ... };
  FooElement.attributeChangedCallback = () => { ... };

  document.registerElement('foo-element', {
    prototype: FooElement
  });
</script>
Web Components 2016 & Polymer v2 by @1000ch

Custom Elements v1

<script>
  class FooElement extends HTMLElement {
    constructor() { ... }
    connectedCallback() { ... }
    disconnectedCallback() { ... }
    attributeChangedCallback() { ... }
    adoptedCallback() { ... }
  }

  window.customElements.define('foo-element', FooElement);
</script>
Web Components 2016 & Polymer v2 by @1000ch

window.customElements

// <foo-element> コンストラクタの参照
const FooElement = customElements.get('foo-element');

// <foo-element> が定義されたタイミング
customElements.whenDefined('foo-element').then(() => {
  console.log('foo-element is defined');
});
Web Components 2016 & Polymer v2 by @1000ch
blue:1px

カスタム要素が定義されるタイミングを待ちたい?

不完全な状態でページが表示されるのを避けるには、 :defined 擬似クラスだけでは難しい

Issue #427 · w3c/webcomponents

Web Components 2016 & Polymer v2 by @1000ch

is 属性の行方…

今のところ WebKit は <button is="foo-button" /> のような Custom Elements によるネイティブ要素の拡張をしない方針を示している

Web Components 2016 & Polymer v2 by @1000ch

HTML Imports はどうなった

Mozilla は ES6 Modules を意識して見送っているThe state of Web Components でも触れているように、ES Modules で解決することを支持している

Web Components 2016 & Polymer v2 by @1000ch

ブラウザサポート状況

  • Shadow DOM v0: Chrome, Firefox w/flag, Safari 10, Opera
  • Shadow DOM v1: Chrome 53, Opera 40, Safari 10
  • Custom Elements v0: Chrome, Firefox w/flag, Opera
  • Custom Elements v1: Chrome 54, Opera 41, Safari TP 14
  • HTML Imports: Chrome, Firefox w/flag, Opera
  • Templates: Chrome, Firefox, Safari, Opera, Edge
Web Components 2016 & Polymer v2 by @1000ch

Safari 10 に Shadow DOM v1 が実装された!

iOS 10 のシェア次第だが、時間の問題

Web Components 2016 & Polymer v2 by @1000ch
Web Components 2016 & Polymer v2 by @1000ch

Safari TP 14 に Custom Elements v1 が実装された (❗❗)

メニューの Develop → Experimental Features → Custom Elements

Web Components 2016 & Polymer v2 by @1000ch
Web Components 2016 & Polymer v2 by @1000ch

Safari の実装が進むことは、開発者にとってかなり大きい

  • モバイルでの利用は現実的になってきた😍
  • あとは Firefox と Edge を応援するだけ👆
  • IE... (´・ω・`).;:...(´・ω...:.;::..(´・;::: .:.;: ...
Web Components 2016 & Polymer v2 by @1000ch

Edgeに実装を進めてもらおう

みんなで Shadow DOM (unprefixed)Custom Elements に投票しよう!

Web Components 2016 & Polymer v2 by @1000ch

Polymer v2 is coming !!

Web Components 2016 & Polymer v2 by @1000ch

Polymer 2.0 Preview

Polymer/polymer リポジトリの 2.0-preview ブランチ

Web Components 2016 & Polymer v2 by @1000ch

日本語訳

Web Components 2016 & Polymer v2 by @1000ch

Polymer Summit 2016 in London on October 17-18

Web Components 2016 & Polymer v2 by @1000ch

Polymer v2 のロードマップ

  • Web Components "v1" の機能のフルサポート
  • Polymer v1.x からのスムースなマイグレーション
  • 標準にそぐわない "leaky" な抽象化を排除
  • Polymer 内部のデータシステムの改善
Web Components 2016 & Polymer v2 by @1000ch

Polymer v1.x

const MyElement = Polymer({
  is: 'my-element',
  created: function () {},
  attached: function() {},
  detached: function() {},
  attributeChanged: function() {},
  ready: function() {}
});
Web Components 2016 & Polymer v2 by @1000ch

Polymer v2

class MyElement extends Polymer.Element {
  static get is() { return 'my-element'; }
  static get config() {
    return { /* properties, observers meta data */ };
  }
  constructor() { super(); }
  connectedCallback() { super.connectedCallback(); }
}

customElements.define(MyElement.is, MyElement);
Web Components 2016 & Polymer v2 by @1000ch

Polymer v1.x の API も一応使える

polymer.html が引き続き提供され、Polymer.dom()Polymer.CompatElement といった Polymer v1.x で提供されてきた API も含まれる

Web Components 2016 & Polymer v2 by @1000ch

ネイティブ API へ移行を強く推奨

Polymer で抽象化してきた API が排除されネイティブの API を使うように。例えば、Shady DOM v1 が提供されることで DOM 操作に関しても Polymer.dom() が不要になる

Web Components 2016 & Polymer v2 by @1000ch

Polymer v2 は is="" をサポートしない

Polymer v1.x の機能は引き続き提供されるが、Type Extension (is="...") の雲行きが怪しいので…

<dom-repeat items="{{items}}">
  <template>...</template>
</dom-repeat>

<custom-style>
  <style>...</style>
</custom-style>
Web Components 2016 & Polymer v2 by @1000ch

Web Components "v1" の API に依存する

故に、サポートされていない環境で使うには webcomponentsjs によるポリフィルが必要である。そして新たなスペックに対応するポリフィルを提供する v1 ブランチの開発が進められている

Web Components 2016 & Polymer v2 by @1000ch

Polymer Elements

v2 のリリースに伴いアップデートされるが、使う側に影響はない(はず)

Web Components 2016 & Polymer v2 by @1000ch

Polymer v2-preview を今すぐ試したい?

$ bower install --save Polymer/polymer#2.0-preview
Web Components 2016 & Polymer v2 by @1000ch

まとめ

Web Components 2016 & Polymer v2 by @1000ch
まとめ

スペックに関して

  • Shadow DOM v1 も Custom Elements v1 も順当にリデザインされてる
  • Shadow DOM は既に v2 に関する議論がはじまっている
  • HTML Imports だけは先行きが若干不安だが、ひとまず webcomponentsjs のポリフィルに頼る
  • WebKit の実装進捗によって モバイル利用が現実的になりつつある
Web Components 2016 & Polymer v2 by @1000ch
まとめ

使い方に関して

  • スコープを解決するためのツールは沢山でてきたが、ツールありきのアプローチでは可搬性が担保されない
  • 今こそみんなで使っていこう(流行らなければ過去の遺物になってしまう
  • 開発の未来は C omponent D riven D evelopment
Web Components 2016 & Polymer v2 by @1000ch

おわり

Web Components 2016 & Polymer v2 by @1000ch