Technote

by sizuhiko

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のイベントカレンダーや検索結果に出ないので、解決方法知っている人がいたら教えてください…

MACが熱暴走したときの原因と対応策

2017年は、ほとんどアウトプットできなかったので、2018年はBlog書くぞーと思っていたのに、もう23日です。どうも…

さて、皆さんは虹が好きですか?

  • 雨が降っていたけど、晴れて虹が出ていた。キレイだねー
  • ダブルレインボー珍しい
  • ラルクの虹…

とか、まぁ良いイメージあるじゃないですか。 でも マッキントッシュ/Macintosh (通称 Mac)では は最悪なイメージです。 Windows をお使いの方だと 砂時計 なわけですが、それよりも になるときは邪悪で、ほぼフリーズに近いです。

またあいつがやってきた

当方は MacBook Pro(13-inch,2017)、機種IDでいうと MacBookPro14,1 を使っています。本記事執筆時点の最新版は MacBookPro14,2 です。

半年ぐらい前か、頻繁にMacがフリーズすることがあって、そのときは Docker for Mac が「応答なし」状況になっていたので、よく「Docker不安定だわー」とつぶやいていました。

そうしたら親切なフォロワーさんが「それ Docker for Mac Edge でしょ。安定板は大丈夫ですよ」と教えてくれたので、ここ最近はフリーズとはおさらばしていたのです。

しかし年が明けて、頻繁にフリーズするようになりました。 仕事にならん…

どうやって死んでいくか

何か操作(特に重いわけでもない)をやっていると、ファンがものすごい勢いで回り始めて、Macは熱くなり、なぜかネットワークインターフェースを使用するプログラム(ブラウザ、Twitterクライアント、Slack、Dockerなど)から「応答なし」になっていきます。次第にマウスポインターはレインボーになり、何も反応しなくなります….

このころ、1日に3回ぐらい、4日間連続ぐらいでフリーズしていたので、イライラMAXになっていました。

オマエか!?

アクティビティモニターを起動したかったのですが、WiFiタブがあるためなのか開けなくて、その状況でどのプロセスが悪さをしているのかわかりませんでした。 そこでずっとアクティビティモニターを起動しっぱなしにして、検証してみることにしました。

何回かのフリーズでは、うまく確認することができなくて「これMacの不良?」と思っていたのですが、ついに原因と思われる挙動を発見しました。

mdworker がCPUを独占している・・・・

そうそしてすぐググりましたよ(残念ながらMacはフリーズしていたので、Androidで)。 「Mac mdworker」みたいなキーワードで検索したところ Macが熱暴走するときの原因と対処法 というサイトが見つかりました。

原因は Spotlight ?

そういえば、よく熱暴走する前に npm install とか git clone/pullcomposer installdocker build とか実行していたなぁと。新しいファイルが見つかると Spotlight がサーチを始めて悪さをするのでしょうか?

とりあえず Spotlight でドライブをサーチしないように Macintosh HD (SSDなのにHDとはコレいかに?みたいなツッコミどころですが…) を対象外に追加します。 私は Spotlight まったく使っていないので気になりません。

と、ここで Finder のサイドバーに Macintosh HD が表示されなかったので Macintosh HD(ハードディスク)をデスクトップ・Finderに表示する方法 macOS Sierra というサイトを参考に追加しました。

どうなったか

それから約1週間、ファンが回りまくることもなくなり、虹も見なくなりました。 作業自体は何も変わっていないので、効果があることは間違いないでしょう。

まぁ今までなんでならなくて、突然新しいMacでなるのかなぁ? そして、なぜ WiFi に関するプロセスから「応答なし」になっていくのかは不明ですが、CPUとWiFiのチップが近くて熱暴走が伝搬する?とか思い、分解記事を読んでみました。

新型「MacBook Pro 13インチモデル」の分解・修理は極めて難しいことがiFixitの分解レポートで判明 で見ると、WiFiチップの位置は数字の3か4のキーの裏あたりでしょうか?USB-Cに近い位置です。 赤枠になっているCPUにすごい近いわけではないのですが(まぁ遠いわけでもないけど)。

ともかく が出なくなって、快適に開発を続けております。

最後に、今年はBlog書くよー