Technote

by sizuhiko

Polymer.co-edo meetup #12 を開催しました

今年3回目となる Polymer.co-edo ミートアップ を開催しました。

今回の議題は

日本発!?のWeb Componentsを作ろう!ということで、一度ブレストした内容を詰めていきたい

ということでPolymer.co-edo meetup #10 を開催しましたで、一度上がった案をベースに議論をしました。

本題の前に

ちょうど少し前、Polymerの公式ブログにPolymer 3.0: Latest previewという記事がアップされました。 こちらの記事は英語ですが、Chromeで開いて日本語に自動翻訳すれば、英語が苦手な方でも問題なく理解できるようになっていますので、ぜひご覧ください(最近の自動翻訳すごい!)。

ちょうど1つ前の記事が preview-12 では、こうなるよ、という話だったのを前回の #11 で話していたので「Polymer.co-edo の開催に合わせて記事がアップされるなんて、なんて親切なんだ」と勝手に妄想してますw

また、先日行われた templateinstantiationstudy のハイライトや感想も話しました。

Polymer.co-edo では何をやっていきたいか

ということで、本題に戻るのですが、始めて参加される方がいたので、コミュニティ/勉強会として何をやっていきたいか、というのをおさらい。

  • 日本発の Web Components を開発/発信したい
  • Web Components の開発フレームワークとして Polymer を推したい
  • Polymer を学ぶ人が気軽に来て学習/相談できるコミュニティにしたい(ハンズオンするとかも)

Polymer で Web Components を作る意味として、個人的な想いを少し話しました。

Webサイトを作るとき、昔からフレームワークやライブラリは、どんどん変わってきました。 その中でライブラリの中心にいたのが jQuery だと思っています。もちろん今でも使われているし、 サイトに簡単な部品を設置するには jQuery だったり、それをベースとした Bootstrap ライブラリを使ったりします。 しかし、それらはモバイル端末で見ると十分なパフォーマンスを得られなかったり、他のフレームワークと衝突してしまう、といったことがおきたりします。

Web Components は、ブラウザの低レベルのAPIを使うことで、フレームワークを超えて部品を共通化することが可能だと思っています。 もちろん部品を組み合わせることでアプリケーションになることも可能です。 今日 Shadow DOMなどのWeb Componentsの要素単位で見れば、主要フレームワークで利用可能な(標準サポートされている)ものもあります。 ですので、そこでPolymerがという話ではなく、同じ会社でもプロジェクトによっては使うフレームワークが違っていたりすることはあるし、 OSSでUI部品を公開するとき多くの人に使ってもらうには、特定のフレームワークに依存した形でなく webcomponents.org で共有するエコシステムみたいなのができたら良いなと思っています。

このような視点で考えると、作るもののアイデアが jQueryやBootstrap であったものを置き換えたり、どこかのサイトで表示されているものを模したものだったりするなぁというのは、自然な流れに感じています。

#10で出たアイデアのおさらいと、新しいタグのブレスト

#10 で出たアイデア以外に何かないか、新しい人も来ていたので、もう一度ブレストしました。 まずあたりをつけたのが、日本のサービスでAPIを公開しているところはないか?それを使ってタグが作れないか?というところです。

そうすると意外とAPIって開いてなかったり、開いていてもサイト上で使うものだったりして、利用規約が Web Components に向いていない(サイトにバナーなどを埋め込んでくださいなど)ことがありました。 こういった利用規約は、Web Components 自体に入ってなくても良いような気がしますが、カスタムタグを利用する人に、どうやって守ってもらうかとか難しいなぁと。

で、LINEの共有ボタンとかないねーとか、有り体な話題で終わるかと思っていたころ、1つの発想転換がありました。

今回採用した新しいアイデア

埋め込みタグ です。昔 jQuery とかでリンクにホバーすると、サイトの概要がポップアップされるようなものがあったのは覚えています。 また、hatena とか使うとき、他の hatena 記事へリンクを貼ると、埋め込みタグ表示にできたりするじゃないですか。 埋め込みタグがあるサービス、例えばTwitterやSlide系のサイトは良いのですが、自分のブログなどに埋め込みタグがないサイトのリンクとして 埋め込みタグをつけれたら便利 というものです。

旅行に行ったブログを書くとき、レストラン行ったら食べログサイトの埋め込みタグを入れたいかもしれないし、ホテルや観光スポットの公式サイトの埋め込みタグを入れたいかもしれないです。 単なるリンクよりも良いですよね!

まずはじめにプロトタイプとしては、直接サイトのHTMLをもってきて meta タグの OGP を埋め込みタグ風に表示する(つまり自分のサイトに Facebook の共有表示を埋め込む感じ)のを目指します。 HTMLだけならテキストでそれほど容量もないし、画像ほど重くはないと思っていますが、サービスとして探して見たら意外となかったりしたので、OGP情報だけをキャッシュするサービスを併せて作っても良いかなーとも思っています。

これ自分のブログにも埋め込みたいし、早く使いたいですw

次回は

4/23(月) の予定です。Doorkeeperのコミュニティページに今年の予定も書いてあるので参考にしてください。

また、春と秋に1回ずつハンズオンもやりたいと思っています。 Doorkeeperのコミュニティページ のメールか、Facebookグループ Polymer Japan などでのアナウンスをお待ちください。

Polymer.co-edo meetup #11 を開催しました

今年2回目となる Polymer.co-edo ミートアップ を開催しました。

今回の議題は

Web Componentsを作るにあたり、いくつか必要な開発ツールがあるので、その解説と体験がメインになります。

ということで、必要なツールと、その使い方/書き方について学習しました。

  • polymer-cli の使い方
  • polymer test を使ってみよう

開発環境をととのえる

ちょうど少し前にYouTubeのGoogle Chrome DevelopersチャンネルBuilding an Element in Polymer 2という動画シリーズ1から5がアップされました。 こちらの動画は英語ですが、字幕をONにして日本語に自動翻訳すれば、英語が苦手な方でも問題なく理解できるようになっていますので、ぜひご覧ください。

今回はBuilding an Element in Polymer 2: Install Tools & Initialize Project (Part 1 of 5)が議題とマッチしていたので、一旦ビデオを見ならが進めました。

はじめに polymer-cli をインストールしましょう。

$ npm install -g polymer-cli

動画の中でも言っていますが、いろいろなものが入るので、結構時間がかかります。

次に bower をインストールします。

$ npm install -g bower

polymer helpbower help などを実行して、コマンドが正常にインストールされているか確認しましょう。

自動テストのしくみ

Polymer はテストコマンドとして polymer test を用意しています。 このコマンドは、polymer-cliのリポジトリソースコードを読むとわかりますが、このコマンドはweb-component-testerへのエイリアスとなっています。

web-component-tester は Polymerチームによって開発されていますが、Polymer用というわけではなく、Web Components をテストするために既存のテスティングフレームワークを統合したものです。 READMEにも書いてあるとおり、フロントエンドやNode.jsでは馴染みのある、以下のようなツールを使って構成されています。

テストスイートの書き方は、Mocha でテストを書いたことがあれば、それほど違和感はないと思います。 Web Components をテストするのに、追加されているのが test-fixture で、テストするエレメントのテンプレートを複数定義しておき、テストで必要な時だけDOMへ追加できます。

またWebサイトはアクセシビリティにも配慮すべきなので、a11ySuite で自動的に問題がないかどうかを検証できます。 参考サイト:Webアプリのアクセシビリティを追求せよ!「インクルーシブ」なマークアップを議論しながら学んでみた

web-component-tester はブラウザを起動してテストを行います。Web Componentsはブラウザの上で動作することを確認することが重要だからです。 しかし、さまざまなブラウザやOSのバージョンマトリクスを用意するのは困難です。 そこでSauce LabsのようなマルチOS/マルチブラウザで動作できるSaaSを利用するのが良いでしょう。 テスト困難はお金で解決できます。 web-component-testerでは、そのためのプラグインが標準で用意されているので、Sauce Labsならすぐに利用できます。 私はBrowserstackを使いたい!、という場合は、Browserstack用プラグインがOSSで公開されているので、試してみてください。

また、テストで起動するブラウザは、自動的に判定されるので、特定のブラウザだけ実行したい場合などは、wct.conf.json というファイルを作ってREADMEを参考に設定します。

もちろんCIでの実行にも配慮されていて、 Gulp や Grunt から実行するインターフェースも用意されています。

テストを実行してみる

実際にどうやってテストが実行されるのか、既存のエレメントで確認しました。 利用したエレメントは、以下の2つです。

どちらも、以下の手順でテストを実行できます。

  • git clone する
  • clone 先にディレクトリを移動
  • bower install を実行
  • polymer test を実行

端末にインストールされているブラウザが自動的に起動して、テストが実行されます。 起動したブラウザは、2ペインになっていて、左側にテスト中のDOM、右側にはテスト結果が表示されます。

既存のエレメントから、基本的なテストの書き方を学ぼう

それぞれのリポジトリのテストコードを読んで、テストコードの書き方を学びます。

まず、どちらのリポジトリも、ルートディレクトリに test というディレクトリがあります。 web-component-testerはデフォルトで、このディレクトリ名を利用するので、よほどのことがない限りこの名前を利用します。

次に test ディレクトリには index.html と、それ以外のテストファイル(複数でも、サブディレクトリでも)を配置します。 まず index.html が読み込まれるので、テストスイートを初期化します。 ほとんどの Web Components で書き方はコピペで良く、変更が必要なのは title タグと、以下のテストスイートに列挙するファイルの一覧だけです。

    WCT.loadSuites([
      'basic.html',
      'basic.html?dom=shadow'
    ]);

重要なこととして、web-component-testerは、デフォルトでは Shadow DOM をOFFにしてテストを実行します。つまり 1行目の basic.html は Shady DOM でテストが実行されます。 もし、Shadow DOM でもテストしたい場合は、2行目のようにパラメータを追加する必要があります。

テストヘルパーの役割

実際のテストコードを見ると、以下のようなテストヘルパーをインクルードしています。

<script src="../../iron-test-helpers/test-helpers.js"></script>
<script src="../../iron-test-helpers/mock-interactions.js"></script>

テストヘルパーを導入すると、テストコードを書くのが容易になります。 代表的なヘルパーメソッドを紹介します。

  • flushAsynchronousOperations : Custom Elements のライフサイクルコールバックを強制的に実行します
  • forceXIfStamp : dom-if を利用しているとき、データバインディングで変更された値の再描画を強制的に実行します。通常はライフサイクルコールバックに入り、非同期で書き換わります
  • pressSpace : 指定したエレメント上でスペースキーが押されたことをエミュレーションします
  • tap : 指定したエレメントでタップ操作をエミュレーションします

これらの操作は、ヘルパーなしに書くと冗長だったり、それだけで疲れてしまうものですが、ヘルパーを利用することでタグ本来の挙動を確認することに集中できます。

また、paper-progress のようにCSSアニメーションを利用する Web Components のテストでは、asyncPlatformFlush を使っています。 このメソッドは web-component-tester で定義されていますが、現時点では DEPRECATED なので、 flush を利用することが推奨されています。

flush は flushAsynchronousOperations と似ていますが、コールバックで呼び出されるか、同期実行になるかが異なります。 公式ドキュメントでは flush を利用するように書いているので、flushを使って書いた方が良いでしょう。 dom-ifdom-repeat などデータバインディングの結果としてDOMの構造が書き換わる場合、変更は非同期で実行されるため、必ず flush が必要です。 私もプロダクション開発のテストコードでは、頻繁に flush を使うことがあります。

それ以外のテストのTIPS

今回はこのあたりで終了時間が少なくなったので、公式ドキュメントで案内されているテストの書き方について、いくつか解説しました。

これらは実際にテストを書くと必要になるので、TIPSとしてリンクを残しておきます。

FAQ

サーバーサイド言語の単体テストは、メソッドを実行して戻り値などを検証するけど、Web Components はプロパティで値を指定して、描画後の状態を取得して検証するの?

基本的には、そのような解釈でも問題ないです。 ただし Web Components にはメソッドも定義できるので、こちらはサーバサイドのテストと同様に記述することも可能です(実際そういう需要があるかは別として)。

仮想環境を使っていると面倒

たしかに web-component-tester はブラウザを起動して Selenium(Web Driver)を使ってテストするので Vagrant や Virtualbox を使った開発環境ではやりずらいです。 なるべくホストOSの環境で開発するのがオススメです。

次回は

3/26(月) の予定です。Doorkeeperのコミュニティページに今年の予定も書いてあるので参考にしてください。

いよいよ、実際に今回アイデア出ししたエレメントを作っていきたいと思います。 今後もワークショップ形式で進めていきたいと思うので、ぜひ参加ください。 新しいエレメントのアイデアも募集しています。

さいごに

写真忘れなかったw!

ワークショップの解説をしている私と参加者、という雰囲気です。

Polymerで作ったWeb Componentで string 型以外の属性を使う場合のTIPS

Dialogflow V1 API Webhook アプリを V2 対応できるミドルウェアを作った

みなさんスマートホーム使っていますか? これからはスマートホームの時代ですね(棒)

ということで、今日本では一番売れているというGoogleHomeのアプリを(Actions on Googleを使って)作ってみようと思うと以下の選択肢があります。

  • Dialogflow
    • GUIから音声対話を構築してアシスタントアプリを作成する
  • Smart home
    • IoT機器(家電)を操作するアシスタントアプリを作成する(昔の呼び名で言うところのダイレクトアクション)
  • Actions SDK
    • SDKとコマンドラインを使ってアシスタントアプリを作成する
  • Converse.AI
    • Dialogflowと似ているけど違うサービスでアシスタントアプリを作成する
  • Trivia
    • トリビアアプリを作るためのテンプレート
  • Personality Quiz
    • クイズアプリを作るためのテンプレート
  • Flash Cards
    • アシスタントアプリ学習用のフラッシュカードテンプレート

まぁおおよそは、以下から選択するわけですが、違いがあります。

  • Dialogflow(構文解析/機械学習機能がある)
  • Actions SDK(構文解析などは自分でやる必要がある)

後者はガチで、前者は簡単にサービスを開始できます。 この記事は、前者のDialogflowについて書いていきます。

Dialogflow

もともとは Api.ai というサービスで Google が買収しました。

参考記事:Googleに買収された自然言語対話プラットフォーム「API.AI」が「Dialogflow」に名称変更!

GoogleHomeのアプリは以下のような流れで実行されます。

  1. GoogleHome(マイク)
  2. Googleアシスタント(音声→テキスト = Speach to Texxt = STT)
  3. Dialogflow(構文解析/学習)
  4. Webhook(必須ではないけど、独自のロジックを書くなら呼べる)

で、来た道を戻り、

  1. WebhookまたはDialogflowからテキストを返却
  2. Googleアシスタント(テキスト→音声 = Text to Speach = TTS)
  3. GoogleHome(スピーカー)

で私たちは音声を聞くことができるのです。

Dialogflow単体でいうと、Googleアシスタントだけではなく、LINEやSlackのBOTも作れます。

※より詳しく何ができるのかは QiitaのDialogflowタグ記事一覧 を参照ください。

Dialogflow API

DialogflowにはAPIがあり、主な利用用途は以下のとおりです。

  • GUIを使わずにCLIから操作できる
    • クライアントアプリを作る
    • アプリの設定を自動化する
  • Webhookのインターフェース

現在の安定板はV1ですが、V2がbeta1として存在しています。

V1とV2の違いは公式サイトに書かれています

また、DialogflowにはEnterprise Edition(現在はベータ版)というのがあって、商用アプリを作る人にはきになるところです。 Dialogflowの割り当てと制限を見るとわかるように、Standard Edition(無料版)には制限があります。 ただし制限だけに限っていうと、先ほどのV1とV2の違いページに書かれているのですが、

Note: These quotas are not applied to requests coming from Google Assistant integration used with Standard Edition agents.

Googleアシスタント経由で使っている分には、Standard Editionでも制限はないということです。

なぜV2を使うのか

たとえば以下のような作業はV1ではできません

  • Dialogflowプロジェクト設定のimport/exportを自動化する(デプロイを自動化するのに必要)
  • Enterprise Editionにとにかく加入して安心したい?(Enterprise Editionは V2 API が必須です)
  • LINEやSlackのBOTを作りたいけど、制限を解除したい

また、DialogflowのWebhookアプリを作るのには、以下の2つから選択します。

当然、後者の方が簡単にアプリを作成できるので、宗教上の理由でNode.js使いたくないという理由がなければ後者の方が良いですね。 ただしリンク先のGitHubみればわかりますが、現時点は

Please note that Dialogflow v2 is not currently supported by this client library.

ということです。

とりあえず作ってみた

いろいろなことがあって、現時点V2使わないといけないかもしれない。 でもV1にも簡単に戻れるようにしたい、みたいな「ふわっとした」状況ってあるじゃないですか。

Dialogflowのデプロイも自動化したいよね、とか。

ということで簡単に「お試し」できるように、リクエストとレスポンスのJSONをV2/V1変換するミドルウェアを作りました。 ミドルウェアにしたのは簡単に取り外せるようにするためです。

V1のアプリは以下のようなコードになります。

const { DialogflowApp } = require('actions-on-google');
const welcome = require('./actions/welcome');

const actionMap = new Map();
actionMap.set('input.welcome', welcome);

const dialogflow = new DialogflowApp({request: req, response: res});
dialogflow.handleRequest(actionMap);

V2のアプリにしたい場合は、エントリポイントのJSだけを変更して、以下のようにすることを想定しています。

const { DialogflowApp } = require('actions-on-google');
const connect = require('connect');
const dialogflowV2 = require('./dialogflow-fulfillment-v2-middleware');
const welcome = require('./actions/welcome');

const actionMap = new Map();
actionMap.set('input.welcome', welcome);

const app = connect();
app.use(dialogflowV2.v2to1());
app.use((req, res) => {
  const dialogflow = new DialogflowApp({request: req, response: res});
  dialogflow.handleRequest(actionMap);
});

app(request, dialogflowV2.v1to2(response));

connectというミドルウェアレイヤーを使って、DialogflowのWebhookアプリでミドルウェアを使えるようにしています。 これはGoogle Cloud Functionsを使った場合の想定で、AWS Lambdaを使った場合は、expressとか使うと思うので、expressのミドルウェアとして差し込んでもらえれば大丈夫です。

  • v2to1() V2リクエストをV1リクエストに変換するミドルウェア
  • v1to2(response) V1レスポンスをV2レスポンスに変換するラッパー

2つのAPIがPublicになっています。

さいごに

JSONを変換するだけの簡単な実装ですが、手元のアプリではV2に切り替えてもうまく動作しました。

まだテストコードとかないので、Pull Requestお待ちしております(もちろんそのうち書く予定ですが…)。

うまく動作しない!などあれば、Issueで報告ください(日本語でOK)。

Polymer.co-edo meetup #10 を開催しました

今年最初の Polymer.co-edo ミートアップ を開催しました。

今回の議題は

今月のテーマは、どうやって Web Components を作りはじめたら良いか?です。 自分たちが作ってみたい Web Components はあるものの、どうやって作り始めて良いかわからないといった悩みを解消できる会になれば良いと思っています。

ということで、まずは最近のPolymer/Web Componentsを取り巻く動向から解説しました。

  • Custom Elements が HTML5.3に入る見込み
  • Polymer で Custom Elements を作るとき、どのスタイル(バージョン)で記述するか

最近のPolymer/Web Components を取り巻く状況

まずHTML5.3に入るかどうかについては suikawiki - HTML 5.3 からリンクされている2つのissueに注目してみることができます。

Web Components を支える技術(仕様)のうち HTML Import でなく Script Module になる Polymer 3.0 からは、3つ以上のブラウザーが実装を持っている状況になるので標準仕様の後押しになっていると考えられます。

Polymer での記述スタイルについては、先日Polymer公式ブログに掲載された The future of elements / What we’re doing with Polymer elements, what we aren’t doing, and why. が参考になります。

現時点で Polymer が提供しているコアエレメントのソースコードを見てみてください。ほとんどは Polymer 1 の形式(ES6クラスを利用しない)です。これは Polymer 2 でも利用可能なハイブリッド形式と呼ばれるものです。一方 Polymer 3 用には 3.0 preview のようなブランチが用意されていて、現時点 Polymer 3 preview 版はこちらを参照するようになっています。

例えば paper-input エレメントでは

  • https://github.com/PolymerElements/paper-input はハイブリッド形式
  • https://github.com/PolymerElements/paper-input/tree/3.0-preview は3.0形式

になっています。

上記ブログにも書かれているとおり、なぜ ES6 形式を提供しないのか?という問いに関しては

Polymerのユーザーに、Polymer 1.0からPolymer 2.0と3.0へのスムーズなアップグレードパスを提供する必要がありました。

と書かれています。これは互換性や移行可用性について、フレームワーク開発者がとても配慮してくれていることがわかります。

2.0のエレメントは、Polymer 1.0と2.0をブリッジする最小限の変更となるように設計されており、ユーザーがアプリケーションを簡単に2.0へアップグレードできるようにしました。 同じ理由から、3.0のエレメントは、既存エレメントを自動変換したES6モジュールで提供されます。 引き続き 2.xと3.xのエレメントはサポートされ、次世代のエレメントを計画しています。

3系の自動変換については、次のセクションでも詳しく書かれています。

エレメントのメンテナンスは、チームにとって重要な作業です。現行のエレメントはハイブリッド形式とし、Polymer modulizerを使用して3.x形式に自動変換することで、 単一のコードベースからPolymerの3つのバージョン(1.x, 2.x, 3.x)をサポートできます。これによりチームの時間を新しいエレメントの開発に割り当てることができます。

つまり私たちが Custom Elements を作るときも同様に、ハイブリッド形式で開発し、3.0へは modulizer を使って変換したコードを用意することでコードベースを1つに保つことができます。

私たちは何を作るのか?

Custom Elements の作成は旧来でいうと jQuery のプラグインや UI ウィジェットを作る作業に似ていると思います。 そこで今回参加したメンバーからは以下のようなアイデアが出ました

  • 郵便番号から住所を検索する入力ボックス
    • これについては gold-zip-input というエレメントがありますが、 An input element that only allows US zip codes なのでそれの日本版になります
  • 天気予報ウィジェット
    • これについても paper-weather というエレメントがありますが、マテリアルデザインでない Yahoo天気予報 みたいな見た目の天気予報が日本っぽいという意見がありました
  • DatePicker
    • あるあるなんですが、なぜかどのプロジェクトでも作ってしまうエレメントがこれですね
  • フォーマット表示
    • 日付/金額など日本でよく使う表示形式に対応したエレメントがあったら良いよね、という意見がありました。これも既存のエレメントにもありますが、より日本の開発者が使い易いスタイルだと良いよねという意見がありました

また Custom Elements は、エレメント名にプレフィックスが必要となります。これについては

  • jp-
  • coedo-
  • edo-

みたいなアイデアが出ているので、実際のエレメントを作る段階で決めたいなと思っています。

How To

ちょっと時間がなくなってしまったので、簡単におさらいしました。

  • GitHubにリポジトリを作る
  • エレメントを作る
  • webcomponents.org に登録する

次回は

2/26(月) の予定です。Doorkeeperのコミュニティページに今年の予定も書いてあるので参考にしてください。

今後は、実際に今回アイデア出ししたエレメントを作っていきたいと思います。 また Custom Elements を作るのに大事な

  • 単体テスト
  • デモページ

の作り方もワークショップ形式で進めていきたいと思うので、ぜひ参加ください。 新しいエレメントのアイデアも募集しています。

さいごに

写真撮り忘れたので、次回からは最初に撮ろう…

あと、コミュニティとイベントの拡散用に connpassのインベントページも作ったのですが、これがconnpassのイベントカレンダーや検索結果に出ないので、解決方法知っている人がいたら教えてください…