CREATIVE X 第2弾
CREATIVE X 第2弾
2018.01.11

こんにちは、先日出張でセブへ行き、初の海外渡航を経験したフロントエンドエンジニアのいなばです。 パスポートの申請ってけっこう大変なんですね。同僚から、セブは「汚い上野」と聞いていましたが、良い例えだなと思いました。

さて、今回はHTML5 Experts.jp「HTML5 Conference 2017特集」のWeb Componentsについて気になること、泉水さんに全部聞いてきました! を読んで、いつの間にかモバイルブラウザではWeb Componentsがポリフィルなしで使える時代が来ていたことに衝撃を受けたので、自分でも実際にやってみることにしました。

※この記事は、2017年10月に執筆されたものです

 

Web Components とは

さっそく 公式サイトを見てみましょう。

Web components are a set of web platform APIs that allow you to create new custom, reusable, encapsulated HTML tags to use in web pages and web apps. Custom components and widgets build on the Web Component standards, will work across modern browsers, and can be used with any JavaScript library or framework that works with HTML. Web components are based on existing web standards. Features to support web components are currently being added to the HTML and DOM specs, letting web developers easily extend HTML with new elements with encapsulated styling and custom behavior.

Webコンポーネントは、再利用可能なカプセル化された新しいカスタムタグを作成して、WebページやWebアプリで使用できるようにするためのWebプラットフォームAPIです。 カスタムコンポーネントとウィジェットはWeb Component標準をベースに構築され、最新のブラウザで機能し、HTMLで動作するJavaScriptライブラリやフレームワークで使用できます。 Webコンポーネントは、既存のWeb標準に基づいています。Webコンポーネントをサポートする機能は、現在HTMLおよびDOM仕様に追加されており、Web開発者がカプセル化されたスタイリングとカスタム動作を備えた新しい要素でHTMLを簡単に拡張できるようにします。

Angular1.x系でいうディレクティブ、AngulerやReact、Vueでいうコンポーネントにあたる独自のHTMLタグがネイティブのAPIで作れてしまうということですね。

まずは触ってみましょう

さらに公式サイトを読み進めると、Webコンポーネントは、下記の4つの主な仕様に基づいていると書いてあります。

  • Custom Elements
  • Shadow DOM
  • HTML imports
  • HTML Template

一番最初に紹介した記事にもあるとおり、ここ最近でHTML importsがオワコンになり、代わりにES Modulesでやりましょう(HTMLはJavaScriptファイルに含めるかtemplateタグで定義するかの2択)という方向に向かっているようです。

正確な情報は原則1次ソース(公式サイト)を読んで知るのが一番なのですが、今回は更新がまだ間にあっていないみたいですね。

小難しい話はいったん置いておいて、まずはやってみましょう。

Custom ElementsとShadow DOM

まずは、どこかで見たことのあるボタンを簡単にWeb componentsで作ってみました。 モバイルで普通に使えると記事にあったので、ChromeもしくはSafariでなら動作するはずです。

customElements.defineの引数にHTMLElementを継承したES6クラスを渡すことにより、見ての通り独自のタグが使えるようになりました。続いてShadow DOMを作成するために、コンストラクタでelement.attachShadow()を呼び、そのままinnerHTMLでstyleとHTMLを突っ込んでいます。

Dev toolsで見るとShadow DOMの存在が確認できますし、lig-btnの直下にある a.btnにはlig-btn内で定義したstyleが一切あたっていません。ポリフィルもトランスパイラも使わずCSSのカプセル化ができる時代が来たことに、感慨深さしか感じませんね。

組み込みHTMLの拡張

クリッカブルなボタンであれば、HTMLAnchorElementを継承すればhref属性を指定することでaタグと同じ挙動をしてくれるのではないか……と試してみたのですが、Chromeの実装が開発中で、現状はまだCustom ElementsはHTMLElementしか継承することができないようでした。

仕様でも揉めているようで、組み込みHTMLタグの拡張ができるようになるのはもう少し先になりそうです。

Chromeの組み込みHTMLタグ拡張の実装状況
https://www.chromestatus.com/features/4670146924773376

slot要素を使いこなす

とはいえ先ほどのボタンの例だと、Shadow DOMのありがたみをあまり感じません。今度はもう少し複雑なHTMLをWeb componentsとして定義してみました。

HTMLの大枠は同じだけど中身だけ複数箇所違う、というケースはよくありますよね。slot要素を使用してShadow DOM内の複数箇所に外からマークアップを差し込めるようにしてみました。

Shadow DOM内のslotのname属性(<slot name=”name”></slot>)がWeb componentsをマークアップで使った時のslot属性のついた子要素(<p slot=”name”>づや</p>)と対応しています。

slot要素を使用する際に、slot属性のついた子要素にあたっているCSSはShadow DOMの中に展開された後も引き継がれる点に注意が必要です(demoでは意図的にグローバルなCSSでづやさんの文字色を赤くしています)。

おわりに

今回はCustom ElementsのHTMLテンプレートを定義できる機能とShadow DOMに焦点をあてて、簡単にWeb componentsに触れてみました。現状ポリフィルなしで使えるのはモバイルサイトだけと言えども、コンポーネント単位でHTMLの記述を一元化できることと、CSSのカプセル化の機能だけでも大規模なWebサイトにおいて抜群に威力を発揮しそうですね。

次回はCustom ElementsにJavaScriptで機能をもたせること、実際の開発に導入するためにBabelやWebpackとの兼ね合いなどについてまで書けたらいいなと思っています。

それでは!

参考