Edited at

Polymer 1.1 リリース

More than 3 years have passed since last update.

こんにちは、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はタグ名が違うだけで中身は同じです。


x-hoge.html

<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があります。


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で宣言してしまえばすべてに適用されます


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に宣言するしかありませんでした。


x-hoge.html

<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ファイルをインポートするのが現実的です。


x-fuga.html

<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として宣言します。


x-style.html

<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 します。


x-hoge.html

<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ですが、世界中のデベロッパーからのフィードバックにより新しい機能が追加され、より実用的になりました。あやふやだったコーディングスタイルも推奨される形が少しずつ定まってきています。今後のアップデートにも期待が持てますね。