doda AIジョブサーチ PWAとパフォーマンスの話

doda AIジョブサーチ PWAとパフォーマンスの話

2019.05.22
『#2 フロントエンド技術交流〜新サービスの裏側初公開+LT枠』 の登壇資料です。
https://tech-lounge.connpass.com/event/122454/

45d01c5df7a87588fe3fff1a138681f3?s=128

gyarasu

May 22, 2019
Tweet

Transcript

  1. doda AIジョブサーチ PWAとパフォーマンスの話 Copyright © PERSOL CAREER Co., Ltd. All

    Rights Reserved. パーソルキャリア株式会社 サービス開発本部 吉次洋毅 2019/11/12
  2. 誰︖ • 吉次 洋毅(ヨシツグ ヒロキ) • 1991年⽣まれ(27歳) • 徳⼭⾼専 専攻科修了

    • 経歴 – 某レストラン検索サイトでバックエンドエンジニアなど – パーソルキャリアでエンジニアをしつつ フリーランスで受託開発 & 他社さんの開発やプロジェクトマネジメントのお⼿伝い • 趣味 – ⼀⼈旅&写真&スーパー銭湯 – スマブラ(VIPに⾏けそうで⾏けない) – 筋トレ(予定) • 最近触っている技術 – Javascript(Nuxt.js / Express.js) – PWA – AWS / GCP Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
  3. 今⽇のお話と⽬標 1. パーソルキャリア初のPWA『doda AIジョブサーチ』のご紹介 → 前置きです 2. NuxtベースでPWAを作った話 →「これからPWA作ってみよう」という⼈向け。 3.

    パフォーマンスの計測と改善をした話 →Nuxtアプリケーション/PWAのフロントエンドのパフォーマンスが気になる⼈向け Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
  4. スライドは後ほど公開します︕ connpassでお知らせします Copyright © PERSOL CAREER Co., Ltd. All Rights

    Reserved.
  5. doda AIジョブサーチの ご紹介 Copyright © PERSOL CAREER Co., Ltd. All

    Rights Reserved.
  6. パーソルキャリア初のPWA︕ Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.

    https://doda.jp/AiJobSearch/ ※現時点でスマホ対応のみ • 「イマイチ⾃分に合った検索条件が わからない」、「じっくり転職サイ トを使う時間がない」そんな⼈に向 けた新サービス • 検索ナシ︕ • 希望条件を⼊れて、出てきた求⼈に 対する興味の有無を選ぶだけ︕ • ⽇々賢くなってイイカンジのレコメ ンドをしてくれる というコンセプト 今は最適化されていないので精度よくない 現在内製の機械学習エンジンを鋭意開発中
  7. 使い⽅ Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.

    希望条件 の設定 求⼈の振 り分け いい感じ のレコメ ンド⽣成 求⼈への 応募
  8. DEMO Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.

  9. 転職しようかな〜と思っていて 気になった⽅は是⾮使ってみてください︕ Copyright © PERSOL CAREER Co., Ltd. All Rights

    Reserved. ※doda会員登録が必要なので、登録後にいろいろ メールが来たり電話がかかってきたりしますのでご 了承くださいm(_ _)m
  10. NuxtベースでPWAを作った話 Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.

  11. Nuxt.jsを使っている︖ Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.

  12. PWAを作っている or 作ったことがある︖ Copyright © PERSOL CAREER Co., Ltd. All

    Rights Reserved.
  13. Vue.js×PWAの概観 • 『Vue.jsで始めるPWA』で検索︕(⼀部最新化出来てませんmm) – https://qiita.com/gyarasu/items/2f18edc4ae251180d89e • PWAでできること – ホームスクリーンへの追加(Add to

    Home Screen) – キャッシュ(Service Worker Caching) – プッシュ通知(Push Notification) – バックグラウンド同期(Background Sync) • 気になる制約(iOS12 Safari) – 未対応のAPI • Web Push • Background Sync – 参考: 『Whatʼs new on iOS 12.2 for Progressive Web Apps』 • https://medium.com/@firt/whats-new-on-ios-12-2-for-progressive-web- apps-75c348f8e945 Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
  14. PWAとして何から始める︖ • ホームスクリーンへの追加(A2HS) • キャッシュ(Service Worker Caching) • プッシュ通知(Push Notification)

    • バックグラウンド同期(Background Sync) Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved. まずは取っ掛かりやすいところから︕ ※ただし、iOS SafariでのA2HSはcookieの扱いが 微妙かも…あとプロンプトが出ないので⼿動。
  15. NuxtアプリケーションをPWA化しよう Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.

    https://github.com/nuxt-community/pwa-module ちょっとだけcontributeしてます
  16. pwa-moduleの導⼊ 1. npmパッケージのインストール 2. nuxt.config.jsのmodulesに追加 3. .gitignoreにsw.*(=Service Workerのスクリプト)を追加 ※不要なmoduleは除外できます Copyright

    © PERSOL CAREER Co., Ltd. All Rights Reserved.
  17. A2HSの設定 Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.

    ウェブアプリマニフェスト(manifest.json)に書 くべき内容をそのままnuxt.config.jsに記載すれば OK https://developers.google.com/web/fundamentals/web-app-manifest/?hl=ja
  18. Workboxの設定 Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.

    workboxの設定もnuxt.config.jsに記述
  19. Service Worker Cacheについて • Service WorkerによるCacheは2種類 – Pre Cache –

    Runtime Cache • Pre Cache – 静的なアセットをキャッシュする • nuxt buildしたときのバンドルファイル – Workboxモジュールが有効化されていれば⾃動的にやってくれる • Runtime Cache – 動的なHTTPリクエストをキャッシュする – フロントエンドから⾮同期で呼び出すAPI • Runtime Cacheの戦略 – リソースの特性(更新頻度など)に応じて戦略や保持する期間を設定する – https://speakerdeck.com/gyarasu/pwaji-chu-3?slide=7 Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved. v3で挙動変わったかも 調査中
  20. Service Workerライフサイクル Copyright © PERSOL CAREER Co., Ltd. All Rights

    Reserved. これ、何︖
  21. Service Workerライフサイクル • https://developer.mozilla.org/ja/docs/Web/API/ServiceWorker_API /Using_Service_Workers • skipWaiting – “Use self.skipWaiting()

    anytime before activation to skip installed stage and directly jump to activating stage without waiting for currently controlled clients to close.” – すでにページをコントロールしているSWがある場合も、waitingをスキップしてactive に移⾏する(SWを新しいものに上書きする) • clientsClaim – “Use self.clients.claim() in the active handler to start controlling all open clients without reloading them.” – SWがページをコントロールするようになるのは、activate後に再度ページが読み込まれ たタイミング。初回のページロードのタイミングでコントロールを開始する。 Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
  22. 【まとめ】 NuxtのWebアプリをPWA化するのはとっても簡単︕ Copyright © PERSOL CAREER Co., Ltd. All Rights

    Reserved.
  23. doda AIジョブサーチ パフォーマンス改善の歴史 Copyright © PERSOL CAREER Co., Ltd. All

    Rights Reserved.
  24. Performance Audit Copyright © PERSOL CAREER Co., Ltd. All Rights

    Reserved. ※Simulated Fast3GでのAudit
  25. これって良いの︖ Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.

  26. パフォーマンスの良し/悪しの観点 • 基本的には、スコアが⾼いほど良いと思っておく – パフォーマンスはUXやコンバージョンに⼤きく貢献する • ⼀⽅で、本来Webサービスが提供すべき価値を忘れないようにする – 実際には、スコアが⾼ければ⾼いほど良いとは⼀概には⾔えない… –

    例えば、スコアを伸ばすために本来に必要なコンテンツを削ったりしたら本末転倒… Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
  27. パフォーマンスの良し/悪しの観点 • 基本的には、スコアが⾼いほど良いと思っておく – パフォーマンスはUXやコンバージョンに⼤きく貢献する • ⼀⽅で、本来Webサービスが提供すべき価値を忘れないようにする – 実際には、スコアが⾼ければ⾼いほど良いとは⼀概には⾔えない… –

    例えば、スコアを伸ばすために本来に必要なコンテンツを削ったりしたら本末転倒… Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved. 読み込み時間が0.1秒減ると、売上が1%増加 by amazon.com
  28. パフォーマンスの良し/悪しの観点 • 基本的には、スコアが⾼いほど良いと思っておく – パフォーマンスはUXやコンバージョンに⼤きく貢献する • ⼀⽅で、本来Webサービスが提供すべき価値を忘れないようにする – 実際には、スコアが⾼ければ⾼いほど良いとは⼀概には⾔えない… –

    例えば、スコアを伸ばすために本来に必要なコンテンツを削ったりしたら本末転倒… Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved. (パフォーマンス)×(本来提供したい価値)の最⼤化を⽬ 指すのが基本的な指針
  29. Lighthouseで確認できるパフォーマンス指標 • First Contentful Paint – 初回のテキストもしくは画像が表⽰されるまでにかかった時間 • First Meaningful

    Paint – 主要コンテンツが表⽰されるまでにかかった時間 • Speed Index – ページのコンテンツが⽬に⾒える状態になるまでにかかった時間 • First CPU Idle – メインスレッドでの処理が終わってCPUがアイドル状態になるまでにかかった時間 • Time to Interactive – ユーザ操作が可能になるまでにかかった時間 • Estimated Input Latency – ユーザの⼊⼒に対するアプリの応答速度 Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
  30. Lighthouseのまとめ情報 • 『Lighthouse によるウェブアプリの監査』で検索 – https://developers.google.com/web/tools/lighthouse/ Copyright © PERSOL CAREER

    Co., Ltd. All Rights Reserved.
  31. 開発途中に計測したもともとの姿… Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.

    しかも、本来出したいコンテンツも完全に⼊ってない状態…
  32. どれだけ良くなった︖ 4.3 5.9 5.4 5.9 16.7 3.8 3.8 4.3 5

    5.8 0 2 4 6 8 10 12 14 16 18 First Contentful Paint First Meaningful Paint Speed Index First CPU Idle Time to Interactive ms パフォーマンス指標の⽐較 Before After Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
  33. 開発過程でコンテンツのリッチ化と パフォーマンスの改善を両⽴出来た︕ Copyright © PERSOL CAREER Co., Ltd. All Rights

    Reserved.
  34. パフォーマンス改善でやったこと • バンドルサイズの縮⼩ • 画像の遅延ロード • 必要なリソースのみ読み込み(計測タグ関連) • APIレスポンスの圧縮 •

    CDNの利⽤ • 計測対象画⾯のAPIリクエストの最適化 などなど Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
  35. バンドルサイズの縮⼩ Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.

    • Nuxtでは、内包されいてるwebpack-bundle-analyzerを使ってバンドル サイズを可視化することができる • やり⽅は簡単。nuxt.config.jsでbuild.analyzeをtrueで指定してあげる – https://ja.nuxtjs.org/api/configuration-build/#analyze • UIライブラリとしてVuetifyでA-la-carteを利⽤していたが、使⽤するコ ンポーネントやディレクティブのみ読み込むように変更した – https://ja.nuxtjs.org/api/configuration-build/#analyze 1.4MB → 556KB
  36. A-la-carteの罠…︖ • Vuetify⾃体のサイズは⼩さくなったが、pagesのファイルが少しずつ⼤き くなってしまった… • 全体としては30KBの削減にとどまった • pagesのファイル数が増えるとVuetifyを全部読み込む場合よりもむしろ全 体のバンドルサイズが⼤きくなってしまうかも…︖ Copyright

    © PERSOL CAREER Co., Ltd. All Rights Reserved. 特定のライブラリを⼩さくする場合に副作⽤がある可能性も 考えておくのが良い。 ご存知の⽅いらっしゃいましたらご教⽰くださいm(_ _)m
  37. 画像の遅延ロード • vue-lazyloadを使ってファーストビューに含まれない画像は遅延ロード – https://github.com/hilongjw/vue-lazyload Copyright © PERSOL CAREER Co.,

    Ltd. All Rights Reserved. 横スクロールしたら初めて⾒える ようになる画像は遅延ロードする (3枚⽬以降)
  38. 必要なリソースのみ読み込み(計測タグ関連) • doda AI JobSearch(https://doda.jp/AiJobSearch/)はdoda (https://doda.jp/)の括りに含まれるサービス • ⼀⽅でAI JobSearchはターゲットを絞って運⽤しており、dodaで導⼊し ている広告タグや各種ツール系のタグ等は不要。

    • GTMでそれらを設定しているが、AI Job Search側では読み込みたくない ので、GTMのコンテナを分け、必要最低限のタグのみを設定することで対 応。 Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
  39. APIレスポンスの圧縮 • 求⼈情報を取得するためのAPIのレスポンスに、多くの情報を含めている のでレスポンスサイズが⼤きくなってしまっていた • バックエンドのAPIサーバは現在Express.jsで構築しているので、 compressionを使⽤して、APIレスポンスをgzip圧縮した。 – https://github.com/expressjs/compression –

    levelの設定は6(=デフォルト)くらいで圧縮率が頭打ちになったので6にした • 20件程度の求⼈情報を含むAPIのレスポンス • 求⼈⼀覧表⽰⽤と、詳細表⽰⽤でエンドポイントを分けて最適化するよう な対応は別途検討する必要がある Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved. 192KB → 59KB
  40. CDNの利⽤ • バンドルファイルや求⼈画像の静的アセットはCDNに置く • dodaではAkamaiを利⽤中 • CDNの恩恵 – 距離が近くなる(dodaの場合国内向けサービスなのでそこまで恩恵はないかも) –

    デバイスに最適化した画像の配信 – トラフィック分散 – 可⽤性の向上 • Nuxt.config.jsのbuild.publicPathにCDNのURLを指定すると、nuxt build実⾏後、クライアント側のバンドルファイルをCDNをアップロード する – https://ja.nuxtjs.org/api/configuration-build/#publicpath Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
  41. PWAでCDNを使うときの注意点 • CDNにクロスオリジンでアクセスする場合は要注意 • Service WorkerからCDNにアクセスできない問題が発⽣する • 『Nuxt × PWA

    × CDNでハマった件について』 – https://qiita.com/gyarasu/items/005e4c74fa166d048dbe – scriptタグのsrc属性でのクロスオリジン指定はOK(HTML5の仕様) – Service Workerは内部的にjsによってHTTPリクエストを⾶ばしているので、この部分 で引っかかる Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
  42. APIリクエストの最適化 • 計測対象画⾯では初期表⽰時に複数のAPI を呼び出している – いいねサマリ取得API – Yes/Noチェック⽤の求⼈リスト取得API – レコメンドリスト取得API×2

    計4リクエスト • レンダリングは2種類 – SSR: URLに直接アクセスした場合 – CSR: 画⾯下部のタブを押した場合(router.push で移動したとき) • 改善ポイントは2つ – 並列に複数のAPIを呼び出す – SSR/CSRそれぞれに合わせたデータの取得⽅法 Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
  43. APIリクエストの最適化 • もともとは、mounted()内で直列にAPIを呼び出していた – SSR時にコンテンツが⼊った状態で表⽰されない – クライアントサイドでマウントされたあとにAPI呼び出して結果を表⽰するまで待つ必要 がある • fetchの活⽤で解決

    – モチベーションは「SSR時にコンテンツを⼊れた状態で表⽰したい」 →レンダリングされる前にデータをストアに⼊れる必要がある – https://ja.nuxtjs.org/api/pages-fetch/ • 複数APIを並列実⾏ – API呼び出しはvuexのactionsに書いているので、actionsの関数はPromiseを返却する ようにする – 必要なAPI分Promiseを⽣成し、Promise.allで並列実⾏ Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
  44. APIリクエストの最適化 Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.

  45. SSR時に表⽰されない…︕ Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.

  46. “fetch メソッドを⾮同期にするためには Promise を返却し てください。そうすれば nuxt.js はコンポーネントがレンダリ ングされる前に promise が解決されるまで待機します。”

    Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
  47. “fetch メソッドを⾮同期にするためには Promise を返却し てください。そうすれば nuxt.js はコンポーネントがレンダリ ングされる前に promise が解決されるまで待機します。”

    Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved. SSR時にPromiseの解決を待たずに画⾯を返してしまう = コンテンツ部分が空になってしまう
  48. APIリクエストの最適化 Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.

    Promise返してみた。
  49. SSR時に表⽰されるようになった︕ Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.

  50. でもタブで切り替えしたとき(CSR)に 引っかかりが⽣じてしまうようになった… Copyright © PERSOL CAREER Co., Ltd. All Rights

    Reserved.
  51. “fetch メソッドを⾮同期にするためには Promise を返却し てください。そうすれば nuxt.js はコンポーネントがレンダリ ングされる前に promise が解決されるまで待機します。”

    Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved. CSR時にもPromiseが解決されるまで待機してしまう
  52. CRS時はPromiseの解決を待たずに とにかく画⾯を切り替えたい Copyright © PERSOL CAREER Co., Ltd. All Rights

    Reserved.
  53. CRS時はPromiseの解決を待たずに とにかく画⾯を切り替えたい Copyright © PERSOL CAREER Co., Ltd. All Rights

    Reserved. 快適なインタラクションを優先したい
  54. 【解決策】 SSRとCSRで処理を分ける Copyright © PERSOL CAREER Co., Ltd. All Rights

    Reserved.
  55. SSR/CSRに応じたfetch最適化 Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.

  56. その他TIPS • ChromeのAuditでパフォーマンス測定する場合はシークレットモードで ⾏う。通常のモードで⾏うと、インストールしているChrome拡張が邪魔 して、スコアに影響することがある。 – 実⾏後にこれが出てたら要注意。シークレットモードでやり直そう。 Copyright © PERSOL

    CAREER Co., Ltd. All Rights Reserved.
  57. 今後のパフォーマンス関連の展望 • 定期的にパフォーマンスを計測する仕組みづくり – バンドルファイルサイズの可視化をCI/CDに組み込む – フロントエンドの各指標を可視化する仕組みづくり Copyright © PERSOL

    CAREER Co., Ltd. All Rights Reserved.
  58. 最後に1つだけ… Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.

  59. パーソルキャリアでは ⼀緒に働く仲間を募集しています︕ Copyright © PERSOL CAREER Co., Ltd. All Rights

    Reserved.
  60. 終 Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.