先日の Google I/O 2015 にあわせて Polymer 1.0 がリリースされました。めでたい。そこで表題のように、自分で Polymer エレメント(コンポーネント)を作るときの構成の話。
始めるにあたっては PolymerLabs/seed-element をベースにすると便利で、この中には以下のような標準的な構成が示されています。
- bower による依存の解決
- web-component-tester を使ったクロスブラウザのテスト
- iron-component-page を使った API ドキュメントとデモ
web-component-tester
web-component-tester は Polymer エレメントをテストするためのツールで、テストを実行するだけじゃなく Mocha や Async.js など便利なライブラリをテストから利用できるようにしてくれます。Polymer が提供するコンポーネントのテストはこれに依存しているため、実質的な標準ツールと言ってよいでしょう。
wct
コマンドで起動するとローカルでも Chrome、Firefox などを起動して、test 以下のテストをそれぞれのブラウザで実行できます。
iron-component-page
iron-component-page は Polymer エレメントのドキュメントを提供するためのコンポーネントで、body 下に以下のように要素を配置するだけでページの URL から対象のコンポーネントを検出して、それをロードし、API の詳細と、demo ディレクトリがあればデモへのリンクを表示します。Polymer Catalog のようなページがこれだけで作れて、一気にそれっぽさが増しますね。
<iron-component-page></iron-component-page>
この HTML ファイルは基本的にコンポーネントの .html の隣に index.html として置くようです。seed-element をベースにする場合は元からあって、編集する必要もない。
polyserve
上記のドキュメントに関して、bower で入手したコンポーネントや開発中のものをローカル環境で参照するに便利なのが polyserve です。Polymer プロジェクトのルートで以下のようにして起動すれば、bower でインストールしたコンポーネントを http://localhost:8080/components/{element-name}
(デモならさらにその下の /demo/ )で参照できます。
polyserve [-p 8080]
seed-element の構成に従うと、プロジェクトルートに置いているコンポーネントの HTML {my-element}.html も、以下のような bower でインストールされる前提の相対 URL 指定で他のライブラリを読みこむことになります。
<link rel="import" href="../polymer/polymer.html">
このため普通のローカルサーバだと参照先がなくて挙動の確認がおこなえないのですが、polyserve はこの要素も /components/{my-element} 以下で配信してくれるので、依存のロードがうまいこといくようになっています。ここが、気が効いていて便利な点。エレメント名には bower.json が参照されます。
ドキュメントの公開
プロジェクトを GitHub にアップロードするのなら、ドキュメントも GitHub Pages を使いたいところです。先ほどの iron-component-page を使えば標準的な UI が提供されるので、それを使います。
polyserve が行うようなディレクトリ構成(みんな /components/ 以下)にするとすんなりいきますが、単純にやるのだと https://{user}.github.io/{element-name}/components/{element-name}/
といった URL での配信になってしまいます。公式のリポジトリには gp.sh ってスクリプトもあるんですが、これはトップページへのアクセスをコンポーネントのディレクトリにリダイレクトするようになっています。Polymer Catalog のように複数のエレメントを配信する場合はそれでいいのですが、1 つだけの場合ちょっと収まりが悪い。
そこで gh-pages ブランチの /index.html に <base href="...">
要素を置くことで、https://{user}.github.io/{element-name}/
での配信を可能にします。
以上のスクリプトを実行すると components 以下に主役のコンポーネントとその依存をフラットに配置した上で、上記のように細工したドキュメントの index.html を最上位に置いたディレクトリを gh-pages という名前で生成します。この内容を gh-pages ブランチとして push するといい感じになると思います。
vulcanize、polybuild
これで Polymer エレメントを使用したドキュメントページが配信できたわけですが、<link rel="import">
によるインポートは再帰的に行われ、またそのためにネットワーク通信が発生するので結構遅い。これを解決するために、依存するコンポーネントを一枚の HTML にまとめる vulcanize というツールを使うことができます。
vulcanize my-element.html > my-element.build.html
これで HTML も CSS も JavaScript も全部まとまるんですが、まあ全部まとまってもらっても困る(Content-Security-Policy とか)。現在は内部で vulcanize を利用した polybuild があるので、これを使うのがよいということになりそうです(ヘルプがなかったりと、ツールとしての成熟度にはまだ余地がありそう)。
polybuild index.html # index.build.html と index.build.js を生成する
ちなみに Polymer エレメントの自作に関しては以下のビデオを見ると感覚がつかめると思います。0.8 のころの話だけど、大枠は一緒です。
CI
もちろん公開して使ってもらうものであればテストは CI に載せたいし、ドキュメントもウェブでアクセスできるのがいいでしょう。その自動化に今回は Wercker を使います。
Wercker(同僚によると「ウェッキャー」)はいわゆる CI as a Service で、最近 Docker イメージをビルド環境に指定できるようになったらしい。ご無沙汰だったので使ってみました。まあこれはただ使いたかっただけなので、他のサービスでも問題なく応用できると思います。
Wercker でのテスト
wct を使うにはブラウザが必要(ほんとは Sauce Labs も使えるけど、今回はやらなかった)なので、そのための Dockerfile を書きました。motemen/nodejs-java-browsers これは以下がインストールされていて、xvfb-run wct
とすればブラウザを起動してテストが行える環境になっています。
- xvfb
- chrome
- firefox
- nodejs
- java
- git
wercker.yaml の当該部分は以下のとおり。
box: motemen/nodejs-java-browsers build: steps: - npm-install - script: name: bower install code: | ./node_modules/bower/bin/bower install --allow-root --config.interactive=false - script: name: npm test code: | xvfb-run npm test
Wercker でのデプロイ
Wercker では成果物を GitHub Pages に push するステップ(手順)が利用可能なので、これと先ほどのスクリプトを利用すれば簡単に GitHub Pages を更新できます。
deploy: steps: - script: name: generate gh-pages content code: | set -x url=$(git config remote.origin.url) url=${url%.git} name=$(basename $url) user=$(basename $(dirname $url)) user=${user#*:} out=./gh-pages rm -rf $out mkdir -p $out cp -R bower_components $out/components git archive --prefix=components/$name/ HEAD | tar x -C $out git rev-parse HEAD > $out/GIT_REVISION cat $out/components/$name/index.html | sed "s:<head>:<head><base href='components/$name/'>:" > $out/index.html - lukevivier/gh-pages@0.2.1: token: $GITHUB_TOKEN basedir: gh-pages
asciidoctor-element
そういうわけでできたのが asciidoctor-element です。どうぞご利用ください(実装は marked-element の丸パクリなんで見るとこない)。