Web ComponentsをHTML Importsでロードする必要性
Published at 2014-08-30
慣例的に<link rel='import' href='x-element.html'>な感じでロードされているけど、前提として、 HTMLImportsである必要はない 。何故ならば、Web Componentsを構成する4つの仕様はそれぞれ独立しているからである。だから、インポートを使わなくてもdocument.registerElement()でカスタム要素の定義は出来るし、HTMLのひな形を使いたい場合に<template>タグを使っても良い。
HTMLを部品として含む場合
HTMLやCSSを部品として含む場合は、<template>タグや、ShadowDOMを駆使しながらパーツを構成していくので、HTMLファイルに書かざるを得ない。もちろん、JavaScriptだけで書けないこともないんだけど、本質ではない。
先日画像をスクロール同期的にロードする要素、 1000ch/lazyload-image を作ったけど、こちらはHTMLファイルではなく、単一のJSファイル。GitHubが作っている github/time-elements なんかも、time-elements.jsだけで構成されているけど、こういう場合は<link rel='import' href='x-element.html'>ではなく、<script src='x-element.js'></script>で事が足りる。
他のWeb Componentsに依存している場合
<x-element>が<y-element>に依存している場合は以下のように、x-element.html内でy-element.htmlをインポートする。
<link rel='import' href='y-element'>
<template id="tmpl">
<div>This is x-element!</div>
</template>
<script>
var XElementPrototype = Object.create(HTMLElement.prototype);
XElementPrototype.createdCallback = function () {
console.log(document.querySelector('#tmpl'));
};
window.XElement = document.registerElement('x-element', {
prototype: XElementPrototype
});
</script>
そのコンポーネントからの相対パスを得たい
これは @hokaccha 氏が詳しく書いているが、Web Componentsとして配布するときに、画像等のサブリソースを含む場合は一工夫が必要になる。
例えば<x-element>というカスタムエレメントが以下のように、imgフォルダの配下にfoo.pngとbar.pngを含んだ構成とする。
x-elementx-element.htmlimgfoo.pngbar.png
bowerなんかでインストールされればx-elementというフォルダごとダウンロードされて、いざインポートするときには<link rel='import' href='bower_components/x-element/x-element.html'>のようになる。
このとき、foo.pngとbar.pngを含むフォルダはbower_components/x-element/imgというパスになるけど、x-element.html側で素直にimg/foo.pngと参照していると、インポート元のドキュメントルートからそのパスを辿ることになるので、上手く参照出来ない。
だからdocument.baseURIを使って相対パスを得たいということになるが、この場合に、HTMLファイルでないとdocument.currentScript.ownerDocument.baseURIと、x-element.htmlからみたベースのURLを辿れない。URLオブジェクトと組み合わせるとアレコレするときに幾分スマートかも。
<script>
var doc = document.currentScript.ownerDocument;
var imgRoot = new URL('img', doc.baseURI);
console.log(imgRoot.href);
// => bower_components/x-element/img
</script>
ネタに走った感あるけど、 https://github.com/1000ch/x-zangief は上記のようなパス解決をしている。