いこレポでのWorkbox導入事例 @PWA Night #7

30ae263378a3109c24f532e4af5cfa82?s=47 HeRo
August 21, 2019

いこレポでのWorkbox導入事例 @PWA Night #7

[PWA Night vol\.7 ~PWAのミライや活用方法をみんなで考えよう~](https://pwanight.connpass.com/event/139818/)で発表した資料です

30ae263378a3109c24f532e4af5cfa82?s=128

HeRo

August 21, 2019
Tweet

Transcript

  1. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. 1 「いこレポ」での

    Workbox導入事例 アクトインディ株式会社 森下泰光
  2. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. 自己紹介 森下

    泰光 • アクトインディ所属 • Webエンジニア ◦ インフラからフロントエンドまで色々やってます • Alexaスキルとかもやってます
  3. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. アクトインディについて メインサービス「いこーよ」は

    Webメディアとして多くの子育て中のご 家族にご利用いただいています。 iko-yo.net 2019/07 PV:6,000万/月 UB:1,000万
  4. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. いこレポについて いこーよの姉妹サイト「いこレポ」はお出

    かけ記事を提供するメディアサイトです。 report.iko-yo.net 2019/07 PV:380万/月 UB:83万/月
  5. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. Railsアプリケーションに Workboxを導入する話

    と Add To Home Screenをカスタムする話 をします
  6. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. Webエンジニアの方?

  7. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. Railsで開発している方?

  8. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. 「Workbox使ってるよ」って方?

  9. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. 2017年7月: サービス開始

    2018年7月: 1周年で200万PV/月超え 2019年8月: 約500万PV/月
  10. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. PWA化の動機 順調にPVを伸ばし成長しているが...

    トラフィックはほとんど検索流入 しかも、ほとんど新規ユーザ。 リピーター増やしたい…。 ホーム画面にアイコン作ってもらえれば増やせるかも。 アイコン追加を促す仕組みがあったはず! Add to Home Screen(A2HS)を使いたい!
  11. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. Add to

    Home Screenとは? 条件を満たすWebサイトに アクセスした際に 「ホーム画面に追加」しませんか? とブラウザが促してくれる仕組み。 実装例:amp.dev これ
  12. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. Add to

    Home Screenの表示条件 • すでにインストールされていないこと • prefer_related_applications: false であること • マニフェストに次の含むこと ◦ short_name または name ◦ 192px と 512px のicons ◦ start_url ◦ display が fullscreen, standalone, minimal-uiのいずれか • HTTPS • ServiceWorker が登録されていること • ServiceWorkerでfetchイベントハンドラを実装していること https://developers.google.com/web/fundamentals/app-install-banners/ Chromeでの話です。
  13. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. いこレポはすでにほとんど満たしていた ✅

    すでにインストールされていないこと ✅ prefer_related_applications: false であること ✅ マニフェストに次の含むこと ◦ short_name または name ◦ 192px と 512px のicons ◦ start_url ◦ display が fullscreen, standalone, minimal-uiのいずれか ✅ HTTPS ✅ ServiceWorker が登録されていること ❌ ServiceWorkerでfetchイベントハンドラを実装していること 実は初期開発で実装していたものの、最後の条件が追加され動かなくなっていた
  14. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. fetch イベントハンドラって?

    ServiceWorkerの主な用途であるキャッシュ その際、ServiceWorkerはサーバへの通信を横取りしてキャッシュがあれば それを返し、通信はしないように実装する。 これを実現するのが、Fetch API。 ブラウザの通信を横取りするためにはfetchイベントハンドラを実装する キャッシュを実装すればA2HSが有効になる!
  15. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. キャッシュを自前で実装するのはなかなか大変 ServiceWorkerを自前で実装するのは面倒。

    しかもキャッシュを実装するのは結構難しい • すでにキャッシュされている場合とされていない場合 • キャッシュとサーバからの取得どっちを優先するか • 古くなったキャッシュの更新 • etc 実装するからにはちゃんとしたい(ちょっとでも速くなったら嬉しい) でも、キャッシュするということ自体がモチベーションではない 楽したい
  16. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. Workboxとは •

    Google製のServiceWorkerサポートライブラリ • 主にオフライン対応をサポート ◦ precache ◦ runtime cache • Webpack Pluginがある これを使います
  17. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. ここから RailsにWorkboxで

    キャッシュを実現する話です
  18. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. いこレポのソフトウェアスタック しっかりRails

    Wayに乗っかったRailsアプリケーション • Ruby 2.6.3 • Rails 5.2.3 ◦ webpacker 4.0.7 ▪ Webpack 4.32.2 ▪ Babel 7.5.5 ▪ workbox-webpack-plugin 4.3.1 ▪ Vue.js 2.6.10
  19. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. いこレポのJavascript・CSS事情 Webpackerを導入しているが、

    Assets Pipelineも使っている というか、Assets Pipelineがメイン Assets Pipeline • ユーザ向けページで使うJS、CSS等のみ扱う Webpacker • <管理画面用Dir>/ 管理画面で使うJS、CSS • front/ ユーザ向けページで使うJS,CSS Assets Pipelineで ビルドされるファイル ユーザ向けページで 使われるもののみ WebPackerで ビルドされるファイル ユーザ向けページで 使うものと 管理画面で使うものが ある
  20. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. キャッシュの方針 ①静的なアセットは基本プリキャッシュ

    • assets/**/* • javascript/packs/front/**/* ②ただし、PC向けアセット、管理画面用アセット はキャッシュしたくない • assets/**/pc/**/* • javascript/packs/<管理画面用>/**/* ③記事で使われている画像は ランタイムキャッシュでキャッシュしたい キャッシュしたい キャッシュしたくない
  21. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. workbox-webpack-pluginの動作 •

    WebPackのプラグインとして設定する • ビルドするとServiceWorkerを実装したJSを生成する • プリキャッシュ ◦ WebPackでビルドした出力はデフォルトでキャッシュする ▪ キャッシュ対象は precache-manifest.****.js に記載される ◦ 設定すればWebPack無関係なファイルもキャッシュできる ▪ キャッシュ対象は sw.jsに記載される • ランタイムキャッシュ ◦ パターンを設定すればキャッシュされるようになる
  22. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. Workbox視点でキャッシュの方針を見ると 1.

    Webpackでビルドするファイルでプリキャッシュしたくないものがある 2. Webpackに無関係なファイルでプリキャッシュしたいものがある 3. ランタイムキャッシュも使いたい
  23. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. Workboxの設定① 1.

    Webpackでビルドするファイルでプリキャッシュしたくないものがある 関連する設定項目 一部をキャッシュから除外したいので exclude が使えそう 設定項目 説明 include 正規表現のリストを設定する。 マッチしたファイルをプリキャッシュに含める 例)include: [/\.html$/, /\.js$/] exclude 正規表現のリストを設定する。 マッチしたファイルをプリキャッシュから除外する 例)exclude: [/\.jpg$/, /\.png$/]
  24. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. Workboxの設定② 2.

    Webpackに無関係なファイルでプリキャッシュしたいものがある 関連する設定項目 設定項目 説明 globDirectory workbox無関係だけどプリキャッシュしたいファイルのベースディレクトリを指定 する 例)globDirectory: '.' globPatterns globDirectoryの中でプリキャッシュするファイルのパターンを指定する 例)globPatterns: ['dist/*.{js,png,html,css}'] globIgnores プリキャッシュから除外したいファイルのパターンを指定する 例)globIgnores: ['**/ignored.html'] modifyUrlPrefix Webpack無関係なプリキャッシュファイルのURLを書き換える CDNのURLに変更する等に利用する 例)modifyURLPrefix: { '/dist': '' }
  25. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. Workboxの設定③ 3.

    ランタイムキャッシュも使いたい 関連する設定項目 設定項目 説明 runtimeCaching 下記の設定を含むオブジェクトのリスト urlPattern キャッシュするURLパターンを正規表現やglobパターンで指定する handler 'NetworkFirst'や'CacheFirsdt'などのキャッシュ戦略を指定する options 有効期限やキャッシュするファイル数、などを設定する
  26. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. • インストール

    • 設定 ◦ workboxの設定だけのファイルを作成 ◦ 上記を config/webpack/production.js で読込(後述) Workboxのインストール
  27. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. キャッシュの方針 ①静的なアセットは基本プリキャッシュ

    • assets/**/* • javascript/packs/front/**/* ②ただし、PC向けアセット、管理画面用アセット はキャッシュしたくない • assets/**/pc/**/* • javascript/packs/<管理画面用>/**/* ③記事で使われている画像は ランタイムキャッシュでキャッシュしたい キャッシュしたい キャッシュしたくない
  28. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. Workboxの設定 設定のポイント

    1. modifyUrlPrefix でCDNからプリ キャッシュファイルを取るように 設定 2. exclude で管理画面用のファイル をプリキャッシュから除外 3. Webpack無関係ファイルのプリ キャッシュ 4. ランタイムキャッシュも設定 1 2 3 4
  29. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. Workboxの設定 1.

    modifyUrlPrefix でCDNからプリキャッシュファイルを取るように設定 環境変数 AWS_S3_HOST_ALIASが定義されていれば、そのホストから取得するように設定 ただし、この設定の影響範囲はWebpack無関係なファイルのみ Webpackで生成されるファイルには適用されない(対処方法は後述)
  30. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. Workboxの設定 2.

    exclude で管理画面用のファイルをプリキャッシュから除外 WorkboxはデフォルトでWebpackでビルドされる出力ファイルをすべてプリキャッシュする exclude は そこから除外するファイルを指定する設定 正規表現にマッチしたファイルを除外する
  31. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. Workboxの設定 3.

    Webpack無関係ファイルのプリキャッシュ キャッシュしたくないパスを設定 プリキャッシュに入れる拡張子を指定 public以下をプリキャッシュ
  32. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. Workboxの設定 5.

    ランタイムキャッシュも設定 ブラウザが使える容量を超えたら削除
  33. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. Rails+Webpackerで使う場合 •

    Workboxの設定は次の様に読み込む config/webpack/production.js publicPath の設定 公開パスを設定する。CDNから取得するように設定 Workboxの設定の読み込み
  34. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. Rails+Webpackerでのビルド •

    rake webpacker:compile で webpak build が実行される • 実際には rake assets:precompile を実行するだけ。 ◦ assets/ 以下のファイルのビルドのあと webpacker:compile も実行される
  35. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. 以上でRails+Webpackerにおける Workboxによる

    キャッシュ設定は完了
  36. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. 結果

  37. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. ここからが本題 Android

    Chromeにおける A2HSの話
  38. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. 条件は満した ✅

    すでにインストールされていないこと ✅ prefer_related_applications: false であること ✅ マニフェストに次の含むこと ◦ short_name または name ◦ 192px と 512px のicons ◦ start_url ◦ display が fullscreen, standalone, minimal-uiのいずれか ✅ HTTPS ✅ ServiceWorker が登録されていること ✅ ServiceWorkerでfetchイベントハンドラを実装していること
  39. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. • いこレポにアクセスすると次のような

    ミニインフォバーが画面下部に表示される デフォルトのA2HS 分かりづらいので改善したい
  40. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. いこレポで実装したA2HS

  41. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. 操作の流れ 条件満たす

    キャンセル ポップアップ表示 終了 ボタンクリック プロンプト表示 キャンセル 終了 追 加
  42. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. beforeinstallpromptイベントハンドラを実装する •

    ミニインフォバーが表示されるタイミングで beforeinstallpromptイベントが発火する • beforeinstallpromptをキャプチャして カスタムポップアップを表示する どうやってカスタマイズするか?
  43. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. 最もシンプルな実装 いずれかをクリックするまで

    ブロック
  44. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. 問題点:キャンセルできない •

    キャンセルしてもキャンセルしても beforeinstallpromptイベントが発火する → ポップアップ表示がアクセスのたびに表示 • ホームアイコンを追加すればもう表示されない → その前にユーザを怒らせてしまう Cookieを使って一定期間表示しないようにした
  45. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. Cookieをセット/確認する関数 これらの関数でCookieをセット、有無を確認する

    Cookieがなければポップアップを表示し、あれば何もしない
  46. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. キヤンセル できるように

    どっちがクリックされたかを判定
  47. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. 課題:効果測定 •

    次を測りたい ◦ どれくらいのユーザがホームアイコンを追加してくれるのか ◦ あるいは追加してくれないのか Google Analyticsにイベントを送って計測
  48. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. 最終的なコード

  49. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. イベント送信箇所 条件満たす

    キャンセル ポップアップ表示 終了 ボタンクリック プロンプト表示 キャンセル 終了 追 加 <open> <popup-ok> <installed> <dismissed> <popup-cancel>
  50. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. 計測結果 イベント

    回数 open 150万 popup-cancel 140万 popup-ok 12,000 dismissed 7800 installed 3800 設置してから記録されたイベント数は次の通り
  51. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. こういうことです 条件満たす

    キャンセル ポップアップ表示 終了 ボタンクリック プロンプト表示 キャンセル 終了 追 加 <open> <popup-ok> <installed> <dismissed> <popup-cancel> 150万 140万 12,000 7800 3800 登録率 0.25%
  52. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. ホームアイコン追加してもらうのは 厳しい

  53. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. まとめ •

    WorkboxによってServiceWorkerのキャッシュは 比較的容易に実装できる • Webpackを利用しているのなら webpack plugin を利用すると楽 • Webpackで出力しないファイルや CDNから配信するファイルのキャッシュも可能 • ホームアイコンを作ってもらうのはなかなか険しい
  54. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. ありがとうございました

  55. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. 参考 •

    Workbox https://developers.google.com/web/tools/workbox/ • Workbox webpack Plugins https://developers.google.com/web/tools/workbox/modules/workbox-webpack-plugin#configuration • Add to Home Screen https://developers.google.com/web/fundamentals/app-install-banners/ • The mini-info bar https://developers.google.com/web/fundamentals/app-install-banners/#mini-info-bar • What is an opaque response? https://blog.fullstacktraining.com/what-is-an-opaque-response/
  56. Copyright (C) 2019 ActIndi, Inc. All Rights Reserved. 本日の発表の元になったブログエントリ •

    workbox を導入してServiceWorkerによるキャッシュを実装した話 https://tech.actindi.net/2018/10/05/083913 • Workboxのプリキャッシュの設定でハマった https://tech.actindi.net/2019/08/02/090212