Service Worker周りの知識をアップデートする（2017年クリスマス版）

PLAID Advent Calendar 2017 23日目。
プレイド @otolabです。イブイブですね（古い）。

面白くて新しい技術はどんどん変化していきます。検索していてもなかなかうまい具合に情報に当たらない。せっかくみつけても情報が古いなんてことはザラ。

というわけで、今回はService Workerに関する最近の動きをまとめ、知識のアップデートを試みます。

前作「[従来のWebアプリの常識を変える! Service WorkerがもたらすWebの未来](http://tech.plaid.co.jp/cong-lai-nowebapurinochang-shi-wobian-eru-service-workergamotarasuwebnowei-lai/?referrer=qiita.com/otolab/items/a4caaee9bcd55e8ee27e)」を2016年の中頃に書いているので、そこからの差分をざっくりと紹介したいと思います。


Service Workerとは？
----------

まずは「とは？」から。

Service Workerとは、Web Workerの一種で、ブラウザで表示しているページ内のスクリプトとは独立して動くスクリプトです。必要に応じてサイトごとに見えないタブが開くイメージでも良いかと思います。

「必要に応じて」というところがミソで、「サーバへのリクエストの発生」「サーバからのプッシュ通知受信」「ネットワーク接続の再確立」など、ページのライフサイクル内ではハンドリングできないイベントに対して作用することができます。

Googleが提唱するPWAなど、Webサイトのアプリ化の要としても注目されており、オフライン時の動作、キャッシュ・アセットの制御、プッシュ通知への対応など、ネイティブアプリと比べて劣っていた機能を強化するものです。

Chrome、Firefoxで先行して実装されており、Webサイトで提供できるサービスを質的に変化させるものとして注目されています。

弊社では2016年のKARTE TALKの一部としてPush APIを使ったブラウザ通知機能を提供しており、その際の知見をエンジニアブログの記事にしました。

そして、あれから1年半の月日が流れました...。


Safari、EdgeでService Workerを使えることが確実に！
-----------------------

なんといってもコレでしょう。

メジャーなモダンブラウザはすべてカバーできることになり、来年はいよいよ導入が進むことになるでしょう。 ~~（Push APIもService Workerの一部として一緒に入ります）~~ _(WebkitにはPush APIが入らない模様。今後調査して追記します)_

マイクロソフト社・アップル社ともに、2016年の夏時点でも議論のテーブルについていることは明らかになっていましたが、今年の夏頃にSafariで実装されることが表明され、直近のニュースとして開発プレビュー版に入ったことが報じられました。

ブラウザ戦争的にはChrome、Firefox陣営の勝利といえます。

ネイティブ vs Webアプリの戦況がどのように変化するか興味深いところです。クーポンアプリ程度なら完全に移行できちゃいますからね。

参考：

* [PWAサイトに2つのXmasプレゼント！Microsoft EdgeとApple Safariが開発版でService Workerをデフォルトで有効に](https://www.suzukikenichi.com/blog/windows-insider-build-and-safari-technology-enables-service-workers-by-default/)
* [「Service Workers が in development」とWebKitが言ったから八月三日はPWA記念日](http://fujii-yuji.net/2017/08/service-workers-in-development-safari.html)


ブラウザ間での送信方法の統一、規格の安定化
----------

2016年12月にPush APIの通信プロトコルが正式版(RFC 8030)として成立、それ以降も関連規格の標準化・安定化が進んでいます。

VAPIDの採用は大きな変化で、送信側の認証をどうするかという問題が解決しました。

VAPIDはサーバの公開鍵をブラウザに直接登録する方式で、受信したコンテンツが正当かブラウザ側から判定できるようになっています。（実装としてはブラウザから依頼を受けてPush Service（中間サーバ）がチェックしている可能性もあります。）

Chromeではmanifest.jsonを設置した上でGCMを使わないといけなかったのですが、現在はそれらが不要になり、完全に標準化されました。

[web-push](https://github.com/web-push-libs/web-push)あたりがシンプルな実装としては定番かなと思います。payloadの暗号化の規格が二転三転している時期もありましたが、その点も完全に安定しました。

参考：

* [[改訂版] Web Pushでブラウザにプッシュ通知を送ってみる](https://qiita.com/tomoyukilabs/items/2ae4a0f708a1af75f13e)


Foreign Fetch、消える
-----------

2015年9月の記事(*1) の時点でも名前の上がっていたForeign Fetchですが、規格として提案されたものの、消えてしまう見込みです。

理由としては、ITPに見られるクロスドメイントラッキング等の防止にあたり、抜け道になってしまうため。

Webアプリ単体ではなく、Web全体を一つのシステムとして考えた場合に重要な機能だったのですが、利便性／セキュリティ・プライバシーのバランスの中で消えたという感じですね。

参考：

* *1 [【Service Worker最前線】仕様策定の現場で何が議論されているのか？](https://html5experts.jp/kinuko/16537/) 
  - 2015年9月の記事です。どのように規格が策定されるのか、という観点で読み返しても面白いです

* [Foreign Fetch が削除されそうな理由と Cookie の double keying](https://blog.jxck.io/entries/2017-09-19/remove-foreign-fetch.html)


実用例が話題に
--------------

Push APIに関しては対応するサービスが増え、紹介記事もやってみた系のものから、実用的なレベルのものが増えて来ているように思います。

また高速化の技法としての実際の採用例も注目を集めました。日経新聞での導入、dev.toでの実証などですね。（阿部寛サイトとの比較の記事とかも面白かったです）

参考：

* [Webでプッシュ通知するサービスを個人開発で作ってみた＋ServiceWorkerPushAPIの実装方法まとめ](https://qiita.com/zaru/items/f6e821052abb1b18bb0b)

* [なぜ dev.to がこんなにも速く、こんなにも自分にとって感動的なのか](https://dev.to/mizchi/-devto--b5)

* [日経電子版 サイト高速化とPWA対応 / nikkei-high-performance-pwa](https://speakerdeck.com/sisidovski/nikkei-high-performance-pwa) (スライド)

* [Mercari Web版 に Workbox で Service Worker を導入する話](http://tech.mercari.com/entry/2017/12/19/workbox)


実用化に向けた調整・機能追加が進む
------------

機能改善は細かいものがおおいですが、いろいろ改善しています。

* 開発環境の改善しています。インスペクタを開いて直接Workerの中身に触れるようになりました
* ServiceWorkerのインストール前のリクエスト特別扱いするため、ヘッダが追加されました。地味ですが、必要なやつです
* fetchのハンドリングを行わないモード（自動的な最適化）が導入されました
* などなど

なお、[Service worker meeting notes](https://jakearchibald.com/2016/service-worker-meeting-notes/)で提案されていた並列化のような大きな変更は行われない方向のようです。Safari、Edgeとも現行の仕様を引き継いで実装しているようです。

参考：

* [ServiceWorkerがちょっとずつスピードアップしてる話](https://qiita.com/amiq11/items/016d00364a2cfe05f040)


ブラウザPush、嫌われ始める
--------------

(´・ω・｀)

...

提供者側でもあるので真摯に受け止めている動きです。

少なくとも、サイトアクセス直後に通知許可を求めるのはアンチパターンになりました。今後は通知ボタンを設置するのが主流になるように思います。RSSに近い感じでしょうか。あとは通知の頻度を抑え、ON/OFFをやりやすく、など、UXとして全体的にユーザの利便性を考えていく必要があるでしょう。

ブラウザ開発サイドも意識をしているようで、Firefoxでは権限制御の管理UIがかなり大きく変更になっています。今後もいろいろチューニングが入ってくるのではないでしょうか。

囚人のジレンマにならないよう、サービス提供者側の工夫も必要になってくるかと思います。

参考：

* [当初の懸念どおりブラウザのプッシュ通知は邪悪に使われはじめている。実装側はクリックまで購読確認を待つべき。](http://mizchi.hatenablog.com/entry/2017/12/05/223520)


最近の個人的なオススメ記事
---------------

今年のAdvent Calendarでも続々と良い記事が上がってますね。

[QiitaのServiceWorkerタグ](https://qiita.com/tags/ServiceWorker)でも多くの記事がヒットします。

比較的新しい記事を幾つかチョイスしてみます。

* [そろそろはじめる Service Worker ＠ SpeeeKaigi #3](http://tech.speee.jp/entry/2017/12/21/111404)

* [Service Worker Offline Cache Techniques](https://qiita.com/kaihar4/items/c09a6d73e190ab0b9b01)

* [HTTP WebPushがIoTで使えない3つの理由](https://qiita.com/toast-uz/items/4cb39fc2c5bb5a1ba3dc)
  - RFC 8030についての記事。Service Workerという文脈とは違う取り上げ方だが興味深く判りやすい



弊社での対応
----------------

内部的な話ですが、今年やった作業など。

* VAPIDへの対応
* サーバサイドのライブラリとして[web-push](https://github.com/web-push-libs/web-push)を採用
* ES6化、rollupで固める
  - indexedDBを使ったログなど機能を増やした

今後はEdgeとSafariの対応を増やす作業も入ってきます。楽しみ...。


最後に
----------

Service Workerはいよいよ本格的な導入の時期に入っていきます。

ベストプラクティスの探訪、フレームワークへの組み込みなど、徐々に「当たり前」の機能になるための動きが進んでいくでしょう。

新しすぎる規格の採用は、調査コストや実装にかかる余分なコストなどを考えると、常に行うべきとは言い難いものです。しかし、Push APIに取り組んだことによって、規格成立の過程からじっくりと眺める機会を得られたことは、自分にとって大きなプラスになったと感じています。

今後とも注視していきたいと思っています。

ではまた。