Polymer 1.1 リリース


こんにちは、lacoです。Google I/OでのPolymer 1.0リリースから2ヶ月半あまり、ようやく1.1がリリースされました。1.0から1.1へのアップデートではある一つの仕様が追加されました。[公式ブログ](https://blog.polymer-project.org/announcements/2015/08/13/1.1-release/)の内容をかいつまんでまとめます。

# アップデート概要
今回のアップデートはただひとつの仕様追加だけを行うマイナーアップデートであり、破壊的変更は一切ありません。

> This is a relatively small, minor release - no breaking changes, and only one feature addition:

追加される仕様には明確な名前は付けられていませんが、本稿では便宜上 **include記法** と呼びます。include記法により、これまでPolymerの課題であった「elementをまたいだスタイリング(theming)」が容易に実現できるようになります。

# 使用例
アプリケーション全体で共通して使いたいスタイルがあるとします。例えば次のような`warning`クラスのような汎用的なクラスです

```css
.warning {
	color: red;
	font-weight: bold;
}
```

ここで`<x-hoge></x-hoge>`と`<x-fuga></x-fuga>`というPolymerElementがあるとします。x-hogeとx-fugaはタグ名が違うだけで中身は同じです。

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

```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>
```

![kobito.1439561108.454657.png](https://qiita-image-store.s3.amazonaws.com/0/20253/9fdc28a7-874b-bb47-81a5-6f5505f9fd93.png "kobito.1439561108.454657.png")


Polymer 1.0ではこの2つの要素に`.warning`を適用するのに次のような方法がありました。

## Shady DOMの場合
1.0ではデフォルトでShady DOMが使用されるため、意識せずにこの方法を使っている場合が多いです。Shady DOMは外から内への一方通行の特殊なCSS Scopeを持ちますので、index.htmlで宣言してしまえばすべてに適用されます

```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>
```

![kobito.1439561305.789145.png](https://qiita-image-store.s3.amazonaws.com/0/20253/a7acbf96-dd75-c948-2bd7-fc9a16bc97c8.png "kobito.1439561305.789145.png")

直感的で特に何の難点もない方法ですが、将来的にShady DOMはオプショナルに
なり、デフォルトがShadow DOMになることは明言されているため、一時凌ぎの解決策ともいえます。また、element側から自身に影響するCSSが把握できません。

## Shadow DOMの場合
Shadow DOMは内外のCSS Scopeが完全に断絶しているため、上記のスタイリングは機能しません。そのため、`.warning`のスタイリングは各PolymerElementに宣言するしかありませんでした。

```html: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>
```

![kobito.1439562825.928220.png](https://qiita-image-store.s3.amazonaws.com/0/20253/255f2cfc-2b4b-7e44-3a89-e72c783b07ac.png "kobito.1439562825.928220.png")

これでは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>
```

![kobito.1439568262.827427.png](https://qiita-image-store.s3.amazonaws.com/0/20253/3d77dbd2-3103-18a8-a79a-65a03d2d4aeb.png "kobito.1439568262.827427.png")


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