昨年末頃からホットなトピックになりつつある「Service Worker[1]」ですが、その先行実装が落ち着いてきた今夏、仕様に対する提案や今後の方向性などについて話し合うF2F(Face-to-Face)ミーティングがサンフランシスコで開かれました。本稿では、このミーティングの様子を中心に、Service Workerの最近、そしてこれからの論点をいくつか解説してみたいと思います。
Service Workerは昨年5月に最初のドラフトが公開されたばかりの新しいAPIですが、Webの前提を変える可能性を持った基盤APIとして注目されています。Service WorkerはあくまでWebの1つのAPIにすぎませんが、このミーティングではWebのこれからの方向性を考える上でも興味深い議論がいくつかなされました。なお、ここで書かれる内容はあくまで議論された論点についてであって、本稿の内容が必ずしも将来仕様にのったり、実装されたりするわけではないことをご了承下さい。
1. 「Service Worker」:Service Worker は “ServiceWorker” や “Service workers”のように表記が揺れて書かれることが多く、その正式名称をめぐってGitHub上でも議論があったほどです。結局、最終的には“service worker”のように(つなげたり大文字にしたりせず)普通の英単語のように書くことで落ち着いたようです。読みやすさも考慮して、本稿では一貫して「Service Worker」と表記しています。
Service Workerとは?
Service WorkerについてはHTML5Experts.jpやHTML5Rocksなどで既にいろいろな解説記事が公開されているため、ここでは概要だけを紹介したいと思います。
Service WorkerはいわゆるWeb Workerの一種類で、Webページとは別にバックグラウンドで実行されるJavascript実行環境のひとつです。ただし、普通のWeb Workerとは異なり、一度インストールされるとブラウザ内に登録され、ネットワーク接続がなくても動作することができます。また、Webページのネットワークリクエストを横取りして任意のレスポンスを返すことができるという強力な特徴があり、Webページに対してオフライン機能やキャッシュによる高速化などを提供することができるのです。
Service Workerの中でネットワークプロキシのようなコードを書けるように、ネットワークからデータを取得(Fetch)するためのFetch APIや、データをディスクにキャッシュ・保存しておくためのCache API[2]の仕様策定が一緒に進んでいます。
また、Service WorkerはWebページが開かれていなくてもそのサイトのJavascriptコードを実行できる基盤を提供するため、Service Workerを拡張する形で従来のWebアプリではできなかったような機能を実現するためのAPIがいろいろ提案されています。その中でも最も注目を集めているのがプッシュ通知を実現するPush APIでしょう。
Service WorkerとPush APIを使ったプッシュ通知についてもいろいろな紹介記事が公開されていています。ChromeではAndroid Chrome も含めて安定版で動作しますので、興味のある方はぜひ試してみてください。
2. Cache API:正確には、Cache APIは現在はService Workerの仕様の一部として策定が進んでいます。
Service Workerの仕様策定
Service Workerの仕様策定はどのように行われているのでしょうか?Service Workerは現在W3CのWeb Applicationsワーキンググループのワーキングドラフトとして公開されており、仕様に関する議論は(最近の流行りにのって)GitHubを中心に行われています。リポジトリはオープンなため、基本的には誰でも議論に参加することができます。とはいえ、議論が白熱しているときは一日に何度も更新されるため、すべての議論や変更をウォッチするのはなかなか大変かもしれません。
GitHubやIRCなど、かなりの議論がオンラインで行われているService Workerですが、判断が難しい問題や全体の方向性に関わる議論はそれだけではなかなか進みません。そのため、(多くのAPIやワーキンググループがしているように)ときどき関係者が実際に集まって顔をあわせて議論するためのF2Fミーティングが開かれています。
F2Fミーティングで議論されたトピック
今年の7月20日に、Googleサンフランシスコオフィス[3]でService Workerについて議論するカジュアルなF2Fミーティングが開かれました。ちょうどChromeでの実装が一段落してきたタイミングで、今後の仕様の議論の進め方やブラウザ間の相互テストの整備について、またService Workerの次のフェーズについてなど、さまざまな議論が行われました。
なお、F2Fミーティングの議事録はこちらに公開されています。また、MozillaのBen Kellyが自身のブログでミーティングのハイライトについて書いており、こちらも参考になります。
今回のF2Fミーティングでは、GitHubで日頃から議論に積極的に参加しているGoogle、Mozilla、Samsungからの参加者に加え、AppleやMicrosoftからも参加があり、活気のあるミーティングとなりました。(なお、ここでの議論はすべて仕様に関するものであり、各組織の意向や実装の予定を示すものでは当然ありません)
今回のF2Fミーティングでは、GitHubでも公開されているアジェンダに添って大体以下の様なトピックが議論されました:
- 今後の仕様議論の方法やF2Fミーティングの頻度など
- “Version 1”の仕様に入れたいもののうち、まだクローズ(解決)されていないissueの総ざらい
- ブラウザ間の互換性とテストプラン
- ナビゲーションやCSP(Content Security Policy)など、他の仕様との統合について
- 複数サイト間でのRPC的なアイディアを実現するnavigator.connectとその代替案であるForeign Fetchについて
- ネットワークリクエストを横取りしないService Workerの可能性について
- Service Workerの有効期間を強制する Service-Worker-Max-Ageヘッダについて
アジェンダには“Version 1” “Version 2”という表現が出てきますが、要は「比較的要件がはっきりしていて現行の仕様にすぐ取り入れたいもの」と、「さらなる議論が必要そうで次フェーズまで待ちたいもの」という感じの位置付けになります。
以下では、上記のリストからService WorkerやWebの今後の方向性につながりそうなトピックをいくつか取り上げ、議論の背景と内容を簡単に説明してみたいと思います。
3.Googleサンフランシスコオフィス:ものすごい余談ですが、MozillaのサンフランシスコオフィスはGoogleオフィスの隣のビルにあります。
Cache APIのHTTPS制限
Cache APIはもともとはService Worker内でレスポンスデータをキャッシュに格納したり置き換えたりする部分をJavascriptからプログラマブルに行えるようにするために考えられたAPIです。しかし、その後Service Worker内だけではなく“window”オブジェクト上、つまり普通のWebページからも使えるようにすべきだという提案があり、Chromeではバージョン43からService Worker外でも使えるようになりました。
しかし、Service WorkerがHTTPSのみでしか使えないのに対し、Cache APIが通常のページ上でも使えるようになるということは、Cache APIが実質HTTPからでも使えるようになることを意味します。すると、例えばHTTPページに埋め込まれたiframeでHTTPSページをロードし、HTTPSオリジンのCacheの中身を書き換えるようなことも技術的にはできるようになります。つまり、Cache APIのストレージを汚染される可能性があるわけです。
こうした指摘を受けて、GitHubでCache APIをHTTPSのみに制限するべきではないかという議論が起こりました。特にMozillaでは新しい機能はすべてHTTPSのみにすべきだという声明を出していることもあり、Cache APIはHTTPで使えるべきではないという強い意見が出されています。一方で、開発者の立場に立った場合、HTTPSのみにすると開発が困難になるのではという意見も出されました。
F2Fでは結局最終的な結論は出ませんでしたが、緩い制限から厳しい制限に後から移行するのはその逆に比べて難しいため、とりあえず実装が進んでいるブラウザではHTTPSのみに制限して様子を見るという暫定的な方向性が示されました。Chromeでもバージョン46からHTTPSのみに制限される予定です。
Cache API自体はService Worker外ではそれほど使い道のないAPIなためマイナーな変更とも言えますが、今後のWebの方向性を見る上では考えさせられる議論です。
navigator.connectとForeign Fetch
Service Workerの次フェーズとも言える仕様として、navigator.connectというAPIが提案されています。これは、異なるオリジンのService Worker間で通信をするための仕様で、navigator.connectのGitHubでは「ページ(document)がなくても動くiframe間のpostMessageのようなもの」と説明されています。複数オリジンのサービスをつないでマッシュアップするためのRPCのような仕組みと言い換えることもできます。
navigator.connectがあると何が嬉しいのでしょうか? 非公式の仕様ドラフトでは、ユースケースとして「オフライン・アナリティクス」や「クラウド・ストレージ・プラットフォーム」などの例が挙げられています。例えば、Google Analyticsをはじめとする多くのアナリティクスはRESTインタフェースを提供しており、オフラインでは当然動きません。ですが、例えばこれらのサードパーティのアナリティクスサービスがそれぞれService Workerを提供し、オフラインでもアナリティクスに送るためのデータを集められようになったとしたらどうでしょうか?
現状のService Workerでは、別のオリジンのサイトからこの仕組を使うには、アナリティクスのサイトをiframeを通じてロードし、そこからアナリティクスのService Workerと通信するしかありません。ですが、navigator.connectが実装されると直接アナリティクスのService Workerと通信できるようになります。同様に、あるサイトから複数のサードパーティのService Workerと通信してさまざまなサービスを受けることが簡単にできるようになる(かも知れない)のです。
navigator.connect はこのように大変強力な提案ですが、議論がまだ詰まってないところが多く、仕様化もこれからの段階です。
これに対し、MozillaはよりシンプルなForeign Fetchという対案を出しています。Foreign Fetchは端的には別のオリジンへのネットワークリクエストをそのオリジンのService Workerがハンドルできるようにする提案で、これによって複数のService Workerを連鎖させることも可能になります。(なお、ほぼ同様のアイディアがnavigator.connectのGitHubではfall-through fetchという名前で説明されています)
F2Fでは、Service Workerが連鎖した場合にCPUの占有率や連鎖の深さをどう制限するのかなどについて議論がされましたが、全体的な結論はVersion 2に先延ばしされることになりました。
ネットワークリクエストを横取りしないService Worker
F2Fに向けて、Mozilla から事前にミーティングで議論したい点のリストが共有されました。興味深いことに、そのうちのいくつかはネットワークリクエストを横取りしない Service Worker の可能性を議論するものになっています。
Service Workerは、本稿の概要でも軽く述べたとおり、そもそもWebページのネットワークリクエストを横取りして動作することを念頭に置いて設計されたAPIです。Service Workerのインストールフェーズやライフサイクル、動作モデルなどはすべてその前提に立って設計されており、逆に言うと「プッシュ通知のようにネットワークリクエストを横取りしないService Workerにとっては不要な」部分も組み込まれていることになります。
例えば、Service Workerは最初のページロードではインストールが走るだけで、そのService Workerはすぐに使えるようにはなりません。これはネットワークリクエストを横取りするService Workerの場合、そのページ自身をロードしたService Workerが足元で置き換わることがないように設計されているためです。しかし、例えばプッシュ通知を使うためだけにService Workerを使ってる場合、この制限は不便なだけであまり意味がありません。
また、プッシュ通知を処理するService Workerとネットワークリクエストを処理するService Workerを分けて書きたいと思ったとしても、Service Workerは「ネットワークリクエストを処理する対象のURLスコープ」で識別されるため、プッシュ通知だけを処理するService Workerにもダミーのスコープを割り当てないといけません。
今回のF2Fではこれらの点は議論されただけであり、現行のVersion 1の仕様に反映されることはなさそうですが、次フェーズに向けて今後さらに議論されていくと予想されます。Service Workerというとまだまだオフライン処理やネットワークプロキシ的な処理の文脈で議論されることが多いですが、そうした前提を超えた文脈でService Workerが議論されるようになってきたことは興味深いことです。
終わりに
F2Fミーティングでは他にも興味深いさまざまなトピックが議論されました。全体的に、これまでのVersion 1のService Workerの仕様の議論では、ブラウザが当たり前のようにやってきたネットワークリクエストの処理をService Workerありの世界でどのように再定義するかに大きな焦点があったように思います。それに対し、次フェーズの議論は、ネットワークリクエストを処理するというモデルを越え、サービス間の連携や様々なバックグラウンドのイベントを処理する、より汎用的な基盤としてのService Workerに焦点が移りつつあるのかもしれません。
次回のF2FミーティングはW3CのTPAC(Technical Plenary / Advisory Committee Meetings)中にやろうという提案がされています。次のTPACは日本の札幌で開催される予定なので、もし興味のある方はウォッチしてみてもいいかもしれません!(10/26には、誰でも参加可能なDeveloper Meetupもあります。)