未経験者が触るPolymer 3.0 preview

[Polymer Advent Calendar 2017](https://qiita.com/advent-calendar/2017/polymer) 6日目の記事です。

---

webcomponentsの実装がブラウザで進み、かなり現実性を帯びてきたのでPolymerも3.0のpreviewが出たということでこの機会に触ってみることにしました。

[Hands-on with the Polymer 3.0 preview](https://www.polymer-project.org/blog/2017-08-23-hands-on-30-preview)

ベースとしてはこの記事をなぞっていくことになります。
JavaScriptを多少書ける人間が、Polymerのファーストインプレッションがどうだったかをお届けできればと思います。

# シンプルに動かしてみる

私は普段Reactで開発することが多いのですが、いままで自分が行ってきたような開発スタイルからどれくらい離れずに開発ができるのかを注視して触ってみることにしました。

## Setup / Import

まずは必要なパッケージをインストールします。この辺りは特に変わらずです。
`polymer@next`でpreview版をインストールするのと、polyfillである`webcomponentsjs`を導入します。

```zsh
$ yarn init

(...generated package.json)

$ yarn add @polymer/polymer@next
$ yarn add @webcomponents/webcomponentsjs
```

適当に`index.html`を用意して、headタグ内に以下のように記述します。
3.0からはHTML ImportではなくES Modulesを使ってファイルを扱うようになるため、`type="module"`を使ってscriptタグを書きます。

```html:index.html
<head>
  <script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
  <script type="module" src="app.js"></script>
</head>
```

Polymerは基本的にブラウザで動作させるものなので、ES Modulesもブラウザの実装で書いていくことになります。ES Modules自体はECMAでsyntaxが決まっているものの、Nodeとブラウザはそれぞれに実装しているため注意が必要です。

参考: http://teppeis.hatenablog.com/entry/2017/08/es-modules-in-nodejs

## Components

ではさっそく表示するためのコンポーネントをPolymerで作っていきます。
シンプルなものでいいので、既存のPolymerコンポーネントをダウンロードしたりせず、１から書いていきます。

```js:component/hello-button.js
import { Element as PolymerElement } from '../node_modules/@polymer/polymer/polymer-element.js';

export default class HelloButton extends PolymerElement {
    static get template() {
        return `<button>Hello</button>`;
    }
}
```

最小のコンポーネントとしてはこれでOKです。
Polymerライブラリから、`Element`をES Modulesのsyntaxでimportします。
それを継承したクラスを作り、staticなgetメソッドとして`template()`というところで文字列を返却します。

次にこれを画面上へ表示させます。

```js:app.js
import HelloButton from './components/hello-button.js';

customElements.define('hello-button', HelloButton);
```
```html:index.html
<body>
  <hello-button></hello-button>
</body>
```

これで画面上に何の変哲も無いボタンが表示されました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/69809/5fbbcba6-f7bc-39eb-672a-5b21ae58270c.png)

余談ですが、webcomponentsは**コンポーネント名に必ずハイフンをつけましょう！**という御触れがあるのですが、これ既存のHTMLタグという予約語とのバッティングを防ぐという理由なんでしょうかね。実際に書いててふと気付きました。

## データを渡す

React経験者としてはPropsを渡したくなります。

```js:component/hello-button.js
import { Element as PolymerElement } from '../node_modules/@polymer/polymer/polymer-element.js';

export default class HelloButton extends PolymerElement {

    static get template() {
        return `
            <button>
                Hello, my name is [[name]].
            </button>
        `;
    }

    constructor() {
        super();
        this.name = this.getAttribute('data-name');
    }

    static get properties() {
        name: {
            type: String
        }
    }
}
```

```html:index.html
<body>
  <hello-button data-name="NEKO"></hello-button>
</body>
```

HTML側で適当な`data-*`属性に情報を持たせます。（よくある）
コンポーネント側では、コンストラクタ実行時に`this.getAttribute()`でそれを取得することができるので、その値をtemplate内で`[[]]`を使って描画することができます。

## イベント

イベントの付与も簡単にできました。
クラス内にメソッドをつくって、template内で`on-*`の形で紐づけておきます。

```js:component/hello-button.js
import { Element as PolymerElement } from '../node_modules/@polymer/polymer/polymer-element.js';

export default class HelloButton extends PolymerElement {

    static get template() {
        return `<button on-click="handleClick">Hello</button>`;
    }

    handleClick() {
        alert('Hello');
    }
}

```

もちろんメソッド内でも参照すれば値の表示できます。

```js
alert(`Hello, my name is ${this.name}`);
```

# Polymer CLI

PolymerのCLIはかなり強力で、Polymerベースの開発をしようと思った場合はこれを中心に構築環境を整えるのはかなり合理的だなと感じました。

ライブラリ自体（あとpolyfillもだけど。）をページから読み込まないといけないので、それもデプロイするために環境はちょっと工夫しないといけないんでしょうか？Polymer CLIだとその辺いい感じにBuildしてくれるので便利でした。

ただ、こちらは3.0のものはまだ無いようなのでリリースが待ちどおしいです。

2.0のCLIのドキュメントはこちら
https://www.polymer-project.org/2.0/docs/tools/polymer-cli

# 感想

今回上記のことを1時間くらいでサクッと学ぶことができました。
ES2015を恒常的に書いていたり、既に何かしらのフレームワークなどでJSを使ってコンポーネントベースの実装を行っている人にとっては、ほぼ同じような知識でPolymerを活用することができるように思えました。

また、3.0になってbowerからnpmになり、ES Modules形式での読み込みになることでJSer的にはかなりとっつきやすかった印象です。（HTML Modulesだとどうなるかなー）

あと、ビルド環境を用意しなくていいのは**非常に非常に楽で良い。**

つまづいた点としては、`[[name]]`や`on-click="handleClick"`など、テンプレートの記述がいまいち覚えきれませんでしたが、これも[lit-html](https://github.com/PolymerLabs/lit-html)を使えばより一貫した書き方ができるかなぁというところでした。

総括：**思っていたよりシンプルだから、みんなもPolymer触ろう！**