未経験者が触るPolymer 3.0 preview


Polymer Advent Calendar 2017 6日目の記事です。


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

Hands-on with the Polymer 3.0 preview

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

シンプルに動かしてみる

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

Setup / Import

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

$ 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タグを書きます。

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コンポーネントをダウンロードしたりせず、1から書いていきます。

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()というところで文字列を返却します。

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

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

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

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

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

データを渡す

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

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
        }
    }
}
index.html
<body>
  <hello-button data-name="NEKO"></hello-button>
</body>

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

イベント

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

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');
    }
}

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

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を使えばより一貫した書き方ができるかなぁというところでした。

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