HTMLインポート

HTMLインポートとは何かと言うと、HTMLの差分ファイルを読み込む機能のことです。
意外にもHTMLには自分の中に別のHTMLを取り込む機能がありません(NodeにはrequireがありますがクライアントサイドのJSにも差分ファイルを取り込む機能がありません。現在importが議論されているみたいですが)。
HTMLインポートはこの差分読み込みを実現する機能です。

ソースコード

とりあえずソースコードは次のようになります。
このソースコードで作るカスタムタグはテンプレートでやったと同じです。

本体HTML(index.html)

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>WebContent Sample</title>
	<link rel="import" href="two-slot.html">
</head>
<body>
	<two-slot id="TwoSlotSample">
		<p slot="inner1" class="left">hoge</p>
		<p slot="inner2" class="right">fuga</p>
		<div class="main">
			<h1>タイトル</h1>
			<div>
				これはメインのコンテンツです。
			</div>
		</div>
	</two-slot>
</body>
</html>

カスタムタグHTML(two-slot.html)

<template id="TmplTwoSlot">
	<div>
		<div>
			<slot></slot>
		</div>
		<div>
			<div class="inline-div">
				<slot name="inner1"></slot>
			</div>
			<div class="inline-div">
				<slot name="inner2"></slot>
			</div>
		</div>
	</div>
	<style>
	.inline-div {
		display: inline-block;
	}
	</style>
</template>

<script>
class TwoSlot extends HTMLElement {
	constructor(){
		super();
	}

	connectedCallback(){
		let sr = this.attachShadow({mode: "open"});
		// documentはindex.htmlなのでdocument.getElementById()はダメ
		// ocument.currentScript.ownerDocumentでこのファイルを見なければならない
		const tmpl = document.currentScript.ownerDocument.getElementById("TmplTwoSlot");
		const clone = document.importNode(tmpl.content, true);
		sr.appendChild(clone);
	}
}

customElements.define("two-slot", TwoSlot);
</script>

説明

2つになったファイル

HTMLファイルが2つになりました。
おかげで素晴らしく見通しがよくなりました。
本体のHTMLにはドキュメントの内容しか書かれておらず、カスタムタグのHTMLにはカスタムタグのことしか書かれていません。

これは特に本体のHTMLにとって素晴らしいです。
レイアウトに関係するタグ付けを無くすまでは行きませんが、2回以上同じ形が出現する構成に関してカスタムタグを用意すれば、ドキュメントの内容だけに集中することができる可能性が高いです。

カスタムタグ側にとってもやはり素晴らしいです。
<template>を使わなければJSに閉じられるので切り出すことは可能なのですが、カスタムタグのCSSによるレイアウトもJSのコード内でやらなければなりません。
これはJSに強くないかJSがわからないデザイナには結構プレッシャーになると思うのですが、<template>内のCSSを触れるのであれば大分プレッシャーが軽減される様に思えます。
また、JSをプログラムする側にとっても必要な部分しかないと言うのはわかりやすくて良いです。

<link rel="import" href="target">

これが差分HTML読み込みです。
簡単ですね。

注意点

JSの29〜32行目ですが注意点です。

読み込まれた差分ファイルのJSのdocumentは読み込んだファイル(この例ではindex.html)になります。そのため、document.getElementById("TmplTwoSlot");とすると<template id="TmplTwoSlot">が見つからずエラーになります。
なのでdocument.currentScript.ownerDocumentから探す必要があります。

動作確認

当然、最初のサンプルと同じになります。

hoge

fuga

タイトル
これはメインのコンテンツです。

まとめ

HTMLインポートによって<template>の価値が非常に高くなりました。

例えば、何ページもあるWebサイトで、基本的に同じレイアウト構造が何度も出る様な場合、レイアウト構造をカスタムタグ化してカスタムタグライブラリにしておけば、それを使うことで各ページをシンプルにマークアップできる様になります。
私のこのサイトは同じ構成になる部分をPHPを使ってサーバサイドでやっていますがその必要が無くなります。

もう一つ重要なのはSEO的に不利にならないことです。現状でもJSで同じ様になる部分(例えばリンクリスト)を生成することはできますが、JSに閉じてしまうのでSEO的に不利です。しかし、<slot>を備えたカスタムタグならリンクはマークアップに現れるのでSEO的に不利になりません。

WebComponentsが主要なブラウザでみんな使える様になったら優れたデザインのカスタムタグライブラリがたくさん作られて、みんなそれを使ってページをマークアップする様になるでしょう。

もう一つ大きいのはサーバサイドへの影響です。
もはやレイアウトの共通化や手間の削減のためにサーバサイドでHTMLを出力する必要がありません。見た目に関することは全部クライアントサイドに任せることができます。
なのでサーバサイドは本当にWebアプリケーションとしての機能に集中することができる様になります。これはサーバサイドの開発者にとっても幸せなことだと思います。