こんにちは、lacoです。Google I/OでのPolymer 1.0リリースから2ヶ月半あまり、ようやく1.1がリリースされました。1.0から1.1へのアップデートではある一つの仕様が追加されました。公式ブログの内容をかいつまんでまとめます。
アップデート概要
今回のアップデートはただひとつの仕様追加だけを行うマイナーアップデートであり、破壊的変更は一切ありません。
This is a relatively small, minor release - no breaking changes, and only one feature addition:
追加される仕様には明確な名前は付けられていませんが、本稿では便宜上 include記法 と呼びます。include記法により、これまでPolymerの課題であった「elementをまたいだスタイリング(theming)」が容易に実現できるようになります。
使用例
アプリケーション全体で共通して使いたいスタイルがあるとします。例えば次のようなwarning
クラスのような汎用的なクラスです
.warning {
color: red;
font-weight: bold;
}
ここで<x-hoge></x-hoge>
と<x-fuga></x-fuga>
というPolymerElementがあるとします。x-hogeとx-fugaはタグ名が違うだけで中身は同じです。
<link rel="import" href="../bower_components/polymer/polymer.html"/>
<dom-module id="x-hoge"> <!-- "x-fuga" -->
<template>
<p class="warning">{{ message }}</p>
</template>
<script>
Polymer({
is: "x-hoge", // x-fuga
properties: {
message: {
type: String,
value: "Hoge!" // "Fuga!"
}
}
});
</script>
</dom-module>
そしてこれらを配置したindex.htmlがあります。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script src="bower_components/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="elements/x-hoge.html"/>
<link rel="import" href="elements/x-fuga.html"/>
</head>
<body>
<x-hoge></x-hoge>
<x-fuga></x-fuga>
</body>
</html>
Polymer 1.0ではこの2つの要素に.warning
を適用するのに次のような方法がありました。
Shady DOMの場合
1.0ではデフォルトでShady DOMが使用されるため、意識せずにこの方法を使っている場合が多いです。Shady DOMは外から内への一方通行の特殊なCSS Scopeを持ちますので、index.htmlで宣言してしまえばすべてに適用されます
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script src="bower_components/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="elements/x-hoge.html"/>
<link rel="import" href="elements/x-fuga.html"/>
<style>
.warning {
color: red;
font-weight: bold;
}
</style>
</head>
<body>
<x-hoge></x-hoge>
<x-fuga></x-fuga>
</body>
</html>
直感的で特に何の難点もない方法ですが、将来的にShady DOMはオプショナルに
なり、デフォルトがShadow DOMになることは明言されているため、一時凌ぎの解決策ともいえます。また、element側から自身に影響するCSSが把握できません。
Shadow DOMの場合
Shadow DOMは内外のCSS Scopeが完全に断絶しているため、上記のスタイリングは機能しません。そのため、.warning
のスタイリングは各PolymerElementに宣言するしかありませんでした。
<link rel="import" href="../bower_components/polymer/polymer.html"/>
<dom-module id="x-hoge">
<style>
.warning {
color: red;
font-weight: bold;
}
</style>
<template>
<p class="warning">{{ message }}</p>
</template>
<script>
Polymer({
is: "x-hoge",
properties: {
message: {
type: String,
value: "Hoge!"
}
}
});
</script>
</dom-module>
これではCSSがすべての要素にハードコードされてしまうので、外部CSSファイルをインポートするのが現実的です。
<link rel="import" href="../bower_components/polymer/polymer.html"/>
<dom-module id="x-fuga">
<link rel="import" type="css" href="../style.css"/>
<template>
<p class="warning">{{ message }}</p>
</template>
<script>
Polymer({
is: "x-fuga",
properties: {
message: {
type: String,
value: "Fuga!"
}
}
});
</script>
</dom-module>
この方法はlink[rel="import"][type="css"]
を使いますが、これはWeb Componentsの仕様の範囲外であり、直感的でもないため改善すべきという声が挙がっていました。
In Polymer 1.1
そこでPolymer 1.1ではelementを跨いで使うスタイルのための仕組みを新しく追加しました。
まず対象のCSSをx-style.html
にPolymerElementとして宣言します。
<dom-module id="x-style">
<template>
<style>
.warning {
color: red;
font-weight: bold;
}
</style>
</template>
</dom-module>
そして、このx-style.htmlをx-hoge、x-fugaそれぞれで include します。
<link rel="import" href="../bower_components/polymer/polymer.html"/>
<link rel="import" href="../x-style.html"/>
<dom-module id="x-hoge">
<template>
<style include="x-style"></style>
<p class="warning">{{ message }}</p>
</template>
<script>
Polymer({
is: "x-hoge",
properties: {
message: {
type: String,
value: "Hoge!"
}
}
});
</script>
</dom-module>
PolymerElementとしてスタイルを扱うことでソースコード内のインポート文に一貫性が生まれてわかりやすくなります。x-style.htmlもHTMLファイルではありますが中身はほとんどCSSファイルと変わらないため、デザイナーとの分業も容易でしょう。
include記法によるスタイリングが新しく導入されますが、これまでどおり<link rel="import" type="css">
によるインポートもサポートされています。しかしいずれは削除される予定ですので早めにinclude記法に切り替えるべきでしょう。
しかしこのアップデートのポイントは <style>
タグは<template>
の中に配置すべき という明確な指針が生まれたところです。これまで<template>
の外でも中でも挙動に違いはなく、デベロッパーガイドでは外に書かれていました。しかしPolymer 1.1からはtemplateタグの内部に配置することが推奨となり、Shadow DOMへのstyleタグの展開において最適化が行われるようになります。今後PaperElements等の公式PolymerElementsもこの指針に従ってアップデートされます。
まとめ
若干の見切り発車感が否めなかったPolymer 1.0ですが、世界中のデベロッパーからのフィードバックにより新しい機能が追加され、より実用的になりました。あやふやだったコーディングスタイルも推奨される形が少しずつ定まってきています。今後のアップデートにも期待が持てますね。