MAKE(旧Integromat)のWeb-hookによるPWA作成
Created , Modified .
* この記事は個人的な実証実験に近い内容である. 実用可能にするには, より標準的な実装手段へ直されたほうがよい要素がある.
概要
MAKE(旧Integromat)のWeb-hookを利用して, Progressive Web Apps(PWA)を作成する. 今回作成したPWAはレコーディングダイエットで食べたものをGoogleスプレッドシートへ記録する飾りっけのないアプリケーションである. 作成したMAKEのScenarioをFig 1に示す. このPWAは最低限度の機能しか持っていないが, 少なくとも私のTORQUE G06ではインストールからのスプレッドシートへの記録に成功した.

Fig 1. 作成したMAKEのScenario
動機
こんなことをしようとした動機は2つある. 1つ目は, 記録を取ることを簡素化したかったこと, 2つ目は, MAKEのWeb-hookに対するパズル的な興味である.
1つ目について, 記録をGoogleスプレッドシートへ記入するとき, 当然スプレッドシートの編集が必要になる. PCで操作する分には特段の不満はないが, スマフォ端末で編集しようと思うと画面が狭いので, ページ送り量が多かったり, セル選択を誤ったりしていた. これらを多少なりとも改善できればと思った.
2つ目について, 初回のコンテンツ獲得さえできればPWAとして機能するはずなら, Web応答ができればよく, それはWeb-hookでもできるのではないか? という興味である. 1つ目の記録をするにあたり, GoogleスプレッドシートのAPIを叩くとなれば, MAKEのWeb-hookを噛ませれば微細な加工がしやすく, また, 端末から操作するならPWAにできると最終的な通信量を抑えつつGUI入力ができる. しかし, PWAを置くためだけにどこぞかのWebサーバーを置く気にもあまりならない. そこで, MAKEのWeb-hookの応答切換えでPWAのコンテンツを返せればよいのではないかと思いついた次第である.
MAKEについて
MAKEはAPI連携のWebサービス(iPaaS)[*1]. 類似としてIFTTT, Zapier, Yoomがある.一般的な, 順次実行, 分岐処理, 配列への繰り返し処理は当然可能であり, 応用利用として連携APIモジュール(MAKEでの処理の1単位)の自作もできる.

本来なら, Redmineのスプリントを自動で立てておくとか, APIをラッパーして多数に同時に加工しながら転送するとかが一番輝くのであって, 今回はその本分でない用途が主要を占めている.
考察と課題
一応, 動作するPWAの作成はできる. しかし, PWAがdomain名だけに紐づいて管理されると, MAKEのWeb-hookは同じdomain名の下に作られるため, 複数Web-hookのPWAらを同時にインストールしておくことはできない. 参考 同じドメインで複数のプログレッシブ ウェブアプリを構築する. [*2]
また, ただ1つしかPWAを作成しないとしても, 初回のアクセスとインストール時にコンテンツ分のアクセスが発生するため, MAKEの実行モジュール数を食い潰していく. MakeのFreeプランでは月あたり1000回の実行モジュールに制限されているため, 闇雲にMAKEに負担をかける開発や運用は避けたほうが良い.
実際の作成物として, まずPWAとしては, 最低限動作しか目指していないため, レイアウトが崩れていたり, 送信をinputのsubmitにしていたり, バリデーションなどがなおざりである. MAKEのScenarioとしては, ベタベタにWeb-hookのレスポンスをそれぞれのコンテンツに対して作成している. これらはMAKEのData storeなどを利用すればもう少し洗練されたフロー構成や更新体制が作れるかもしれない.
ただ, 直近で入力した食べたものを表示できないことが結構不便な点である. 今さっき何を入力したかが分からないので, 同じもの2回登録する不注意や登録したつもりになる不注意を犯しやすい.
詳細
動機のもとになっているレコーディングダイエットのGoogleスプレッドシートは次の2表, 食べたものと食物で管理されている. 作成したPWAはこの2表に対する項目追加を行うアプリケーションである.


Fig 2. Googleスプレッドシート, (上) 表食べたもの 抜粋, (下) 表食物 抜粋
MAKEのWeb-hookでPWAを作成するときの大きな制約はdirectory構造を再現できないことである. 通常のPWAでは, 個別のファイルとしてmanifest.jsonやservice_worker.jsが配置される. しかし, MAKEのWeb-hookではそのポイントにしかアクセスしようがないため, 本来のPWAとしてはおよそ例を見ない, コンテンツURLを常に絶対参照のクエリストリングでやり取りすることを主体にしている.
作成したPWA概要
作成したPWAは2つのForm入力のみでCSSもない1ページで構成している. MAKEのScenarioのフロー構成はGETとPOSTメソッドの大きく2つに分かれる. GETメソッドはさらに通常アクセスなどのキャッシュ時の応答とAJAXな随時応答がある. 少し厄介なのがWeb-hookの構造体定義である.
私のスマフォ端末へインストールしたときの画面がFig 3である.

Fig 3. インストールされたPWAのスマフォ画面
作成したPWAはForm入力を2つ持ち, それぞれ, 食べたものの追加と食物の追加を担う. 食べたものの追加では喫食したときの, 日付, 時間, 食物, 数量(係数)を入力する. このうちの食物は食物の名称リストのプルダウンから選択する方法としている. 食物の追加では, 食物の名称, カロリー, 参考元を入力する.
次のリストがWeb-hookのアドレス(https://hook.eu1.make.com/<###>)を###としたときの, コンテンツの簡易説明である.
- ### or ###?src=index.html
作成したPWAのメインページ, Form入力が2つある
- ###?src=manifest.json
内容後述
- ###?src=service_worker.js
ほとんどコンテンツのキャッシュしか処理がない
- ###?src=icon-512x512.png
作成したPWAのアイコン
- ###?src=icon-192x192.png
作成したPWAのアイコン
- ###?src=icon-180x180.png
作成したPWAのアイコン
- ###?src=screenshot-450x320.png
作成したPWAのインストール時の画像
- ###?src=food-list.json
Formの入力選択肢で食物の名称リスト, これだけキャッシュされない
- ###?to=add-food-data
Form入力で食物を追加する
- ###?to=eat-food
Form入力で食べたものを追加する
manifest.jsonの内容はほとんど最低限な記述であり, 次のとおりである. なおURLが入るところは###に置き換えてある. screenshots
の項はオプションのはずだが, 注意が煩わしいので入れた.
manifest.json
{
"name": "Wheight loss diet by recorded data",
"short_name": "Record-Diet",
"theme_color": "#8a2be2",
"background_color": "#cd853e",
"display": "standalone",
"orientation": "portrait",
"start_url": "###?src=index.html",
"id": "###",
"description": "レコーディング・ダイエット記録フォーム",
"icons": [
{
"src": "###?src=icon-180x180.png",
"sizes": "180x180",
"type": "image/png"
},
{
"src": "###?src=icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "###?src=icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"screenshots": [
{
"src": "###?src=screenshot-450x320.png",
"sizes": "450x320",
"type": "image/png",
"form_factor": "wide",
"label": "Demo Wide"
},
{
"src": "###?src=screenshot-450x320.png",
"sizes": "450x320",
"type": "image/png",
"label": "Demo others"
}
]
}
通常アクセスの応答
通常アクセスやインストール時にはメインページのindex.html, manifest.json, service_worker.js, 他画像へのアクセスが発生する. クエリで要求されることが前提なだけで求められたとおりにレスポンスを返せばよい. ただ, index.htmlはクエリでの指定がない時のデフォルトに設定して, 直接のアクセスに応答できるようにしておく.
また, 作成したMAKEのScenarioで, 画像を返すモジュールは一旦画像をbase64のテキストに変換しておき, モジュールの中でtoBinary(<画像base64エンコードテキスト>;base64)
して応じている. 今回は直接モジュールに設定するためにこのような形にしたが, 別のオンライン上のストレージに画像をおいておけば, その取得方法にも依るけれどもその取得したものを直接指定すればよいだろう.

Fig 4. MAKEの画像を返すモジュールの設定内容
Ajaxな随時応答
コンテンツを返すモジュールのうち, 特殊なのがfood-list.jsonである. これはForm入力に利用されており, アクセスされたときにGoogleスプレッドシートを参照して, 最新の食物の名称リストを提示できるようにしている. 作成したPWAのほうでも最新の食物の名称リストを受け入れられるように, これだけはキャッシュの対象から外している. 常に加工処理をして返すので, 端末からは他の要求よりも時間がかかってから応答が返ってくる[*3].
Googleスプレッドシートから食物の名称リスト取得するモジュールの時点では複数個のバンドルとして出力されるが, それをText aggregatorモジュールで受けることで実行モジュール回数としてはそれぞれ1回ずつのみに抑えられている. ここが上手く抑えられないと容易にMAKEの月間の実行制限に達してしまう.
Form入力受け付け
2つのForm入力受け付けがあるものの, 実際にやってることは来たものをそれぞれの表に追記するだけである. 作成時点ではバリデーションがなおざりだし, 追記に成功しようが失敗しようが端末側でできることはないため, 実際のGoogleスプレッドシートにアクセスする前にOKを返している.
まともにやるなら, スプレッドシートにアクセスした後に応答を返すか, 処理番号を返しておき端末側から処理番号の結果がどうなったかを再度聞き返させるのが良いだろう. 処理番号の応答ではMAKEのData storeなどを利用すれば疑似的なサーバー側キャッシュのシステムが作れると考えられる.
Web-hook構造体定義
ここまでで少し厄介なのはWeb-hookにリクエストを送るときの構造体定義である. MAKEではWeb-hookを作るときの最初に, 利用するパラメータ構造を載せてアクセスすることで, それ以後のモジュールで設定するときのパラメータ名称を自動的に作ってくれる. ただ作成したPWAはFrom入力を2つ持つため, 通常では併存しないパラメータ構造でアクセスする必要がある. またそのためには最終的に利用する予定のパラメータが一通りわかってないといけない[*4].