Polymer 1.1 リリース


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