2019.05.22 『#2 フロントエンド技術交流〜新サービスの裏側初公開+LT枠』 の登壇資料です。 https://tech-lounge.connpass.com/event/122454/
doda AIジョブサーチPWAとパフォーマンスの話Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.パーソルキャリア株式会社サービス開発本部吉次洋毅2019/11/12
View Slide
誰︖• 吉次 洋毅(ヨシツグ ヒロキ)• 1991年⽣まれ(27歳)• 徳⼭⾼専 専攻科修了• 経歴– 某レストラン検索サイトでバックエンドエンジニアなど– パーソルキャリアでエンジニアをしつつフリーランスで受託開発 & 他社さんの開発やプロジェクトマネジメントのお⼿伝い• 趣味– ⼀⼈旅&写真&スーパー銭湯– スマブラ(VIPに⾏けそうで⾏けない)– 筋トレ(予定)• 最近触っている技術– Javascript(Nuxt.js / Express.js)– PWA– AWS / GCPCopyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
今⽇のお話と⽬標1. パーソルキャリア初のPWA『doda AIジョブサーチ』のご紹介→ 前置きです2. NuxtベースでPWAを作った話→「これからPWA作ってみよう」という⼈向け。3. パフォーマンスの計測と改善をした話→Nuxtアプリケーション/PWAのフロントエンドのパフォーマンスが気になる⼈向けCopyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
スライドは後ほど公開します︕connpassでお知らせしますCopyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
doda AIジョブサーチのご紹介Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
パーソルキャリア初のPWA︕Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.https://doda.jp/AiJobSearch/※現時点でスマホ対応のみ• 「イマイチ⾃分に合った検索条件がわからない」、「じっくり転職サイトを使う時間がない」そんな⼈に向けた新サービス• 検索ナシ︕• 希望条件を⼊れて、出てきた求⼈に対する興味の有無を選ぶだけ︕• ⽇々賢くなってイイカンジのレコメンドをしてくれるというコンセプト今は最適化されていないので精度よくない現在内製の機械学習エンジンを鋭意開発中
使い⽅Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.希望条件の設定求⼈の振り分けいい感じのレコメンド⽣成求⼈への応募
DEMOCopyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
転職しようかな〜と思っていて気になった⽅は是⾮使ってみてください︕Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.※doda会員登録が必要なので、登録後にいろいろメールが来たり電話がかかってきたりしますのでご了承くださいm(_ _)m
NuxtベースでPWAを作った話Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
Nuxt.jsを使っている︖Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
PWAを作っている or 作ったことがある︖Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
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-75c348f8e945Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
PWAとして何から始める︖• ホームスクリーンへの追加(A2HS)• キャッシュ(Service Worker Caching)• プッシュ通知(Push Notification)• バックグラウンド同期(Background Sync)Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.まずは取っ掛かりやすいところから︕※ただし、iOS SafariでのA2HSはcookieの扱いが微妙かも…あとプロンプトが出ないので⼿動。
NuxtアプリケーションをPWA化しようCopyright © PERSOL CAREER Co., Ltd. All Rights Reserved.https://github.com/nuxt-community/pwa-moduleちょっとだけcontributeしてます
pwa-moduleの導⼊1. npmパッケージのインストール2. nuxt.config.jsのmodulesに追加3. .gitignoreにsw.*(=Service Workerのスクリプト)を追加※不要なmoduleは除外できますCopyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
A2HSの設定Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.ウェブアプリマニフェスト(manifest.json)に書くべき内容をそのままnuxt.config.jsに記載すればOKhttps://developers.google.com/web/fundamentals/web-app-manifest/?hl=ja
Workboxの設定Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.workboxの設定もnuxt.config.jsに記述
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=7Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.v3で挙動変わったかも調査中
Service WorkerライフサイクルCopyright © PERSOL CAREER Co., Ltd. All Rights Reserved.これ、何︖
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 anddirectly jump to activating stage without waiting for currently controlled clientsto close.”– すでにページをコントロールしているSWがある場合も、waitingをスキップしてactiveに移⾏する(SWを新しいものに上書きする)• clientsClaim– “Use self.clients.claim() in the active handler to start controlling all open clientswithout reloading them.”– SWがページをコントロールするようになるのは、activate後に再度ページが読み込まれたタイミング。初回のページロードのタイミングでコントロールを開始する。Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
【まとめ】NuxtのWebアプリをPWA化するのはとっても簡単︕Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
doda AIジョブサーチパフォーマンス改善の歴史Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
Performance AuditCopyright © PERSOL CAREER Co., Ltd. All Rights Reserved.※Simulated Fast3GでのAudit
これって良いの︖Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
パフォーマンスの良し/悪しの観点• 基本的には、スコアが⾼いほど良いと思っておく– パフォーマンスはUXやコンバージョンに⼤きく貢献する• ⼀⽅で、本来Webサービスが提供すべき価値を忘れないようにする– 実際には、スコアが⾼ければ⾼いほど良いとは⼀概には⾔えない…– 例えば、スコアを伸ばすために本来に必要なコンテンツを削ったりしたら本末転倒…Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
パフォーマンスの良し/悪しの観点• 基本的には、スコアが⾼いほど良いと思っておく– パフォーマンスはUXやコンバージョンに⼤きく貢献する• ⼀⽅で、本来Webサービスが提供すべき価値を忘れないようにする– 実際には、スコアが⾼ければ⾼いほど良いとは⼀概には⾔えない…– 例えば、スコアを伸ばすために本来に必要なコンテンツを削ったりしたら本末転倒…Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.読み込み時間が0.1秒減ると、売上が1%増加by amazon.com
パフォーマンスの良し/悪しの観点• 基本的には、スコアが⾼いほど良いと思っておく– パフォーマンスはUXやコンバージョンに⼤きく貢献する• ⼀⽅で、本来Webサービスが提供すべき価値を忘れないようにする– 実際には、スコアが⾼ければ⾼いほど良いとは⼀概には⾔えない…– 例えば、スコアを伸ばすために本来に必要なコンテンツを削ったりしたら本末転倒…Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.(パフォーマンス)×(本来提供したい価値)の最⼤化を⽬指すのが基本的な指針
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.
Lighthouseのまとめ情報• 『Lighthouse によるウェブアプリの監査』で検索– https://developers.google.com/web/tools/lighthouse/Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
開発途中に計測したもともとの姿…Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.しかも、本来出したいコンテンツも完全に⼊ってない状態…
どれだけ良くなった︖4.35.95.45.916.73.8 3.84.355.8024681012141618First Contentful Paint First Meaningful Paint Speed Index First CPU Idle Time to Interactivemsパフォーマンス指標の⽐較Before AfterCopyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
開発過程でコンテンツのリッチ化とパフォーマンスの改善を両⽴出来た︕Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
パフォーマンス改善でやったこと• バンドルサイズの縮⼩• 画像の遅延ロード• 必要なリソースのみ読み込み(計測タグ関連)• APIレスポンスの圧縮• CDNの利⽤• 計測対象画⾯のAPIリクエストの最適化などなどCopyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
バンドルサイズの縮⼩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/#analyze1.4MB → 556KB
A-la-carteの罠…︖• Vuetify⾃体のサイズは⼩さくなったが、pagesのファイルが少しずつ⼤きくなってしまった…• 全体としては30KBの削減にとどまった• pagesのファイル数が増えるとVuetifyを全部読み込む場合よりもむしろ全体のバンドルサイズが⼤きくなってしまうかも…︖Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.特定のライブラリを⼩さくする場合に副作⽤がある可能性も考えておくのが良い。ご存知の⽅いらっしゃいましたらご教⽰くださいm(_ _)m
画像の遅延ロード• vue-lazyloadを使ってファーストビューに含まれない画像は遅延ロード– https://github.com/hilongjw/vue-lazyloadCopyright © PERSOL CAREER Co., Ltd. All Rights Reserved.横スクロールしたら初めて⾒えるようになる画像は遅延ロードする(3枚⽬以降)
必要なリソースのみ読み込み(計測タグ関連)• 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.
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
CDNの利⽤• バンドルファイルや求⼈画像の静的アセットはCDNに置く• dodaではAkamaiを利⽤中• CDNの恩恵– 距離が近くなる(dodaの場合国内向けサービスなのでそこまで恩恵はないかも)– デバイスに最適化した画像の配信– トラフィック分散– 可⽤性の向上• Nuxt.config.jsのbuild.publicPathにCDNのURLを指定すると、nuxtbuild実⾏後、クライアント側のバンドルファイルをCDNをアップロードする– https://ja.nuxtjs.org/api/configuration-build/#publicpathCopyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
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.
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.
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.
APIリクエストの最適化Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
SSR時に表⽰されない…︕Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
“fetch メソッドを⾮同期にするためには Promise を返却してください。そうすれば nuxt.js はコンポーネントがレンダリングされる前に promise が解決されるまで待機します。”Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
“fetch メソッドを⾮同期にするためには Promise を返却してください。そうすれば nuxt.js はコンポーネントがレンダリングされる前に promise が解決されるまで待機します。”Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.SSR時にPromiseの解決を待たずに画⾯を返してしまう= コンテンツ部分が空になってしまう
APIリクエストの最適化Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.Promise返してみた。
SSR時に表⽰されるようになった︕Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
でもタブで切り替えしたとき(CSR)に引っかかりが⽣じてしまうようになった…Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
“fetch メソッドを⾮同期にするためには Promise を返却してください。そうすれば nuxt.js はコンポーネントがレンダリングされる前に promise が解決されるまで待機します。”Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.CSR時にもPromiseが解決されるまで待機してしまう
CRS時はPromiseの解決を待たずにとにかく画⾯を切り替えたいCopyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
CRS時はPromiseの解決を待たずにとにかく画⾯を切り替えたいCopyright © PERSOL CAREER Co., Ltd. All Rights Reserved.快適なインタラクションを優先したい
【解決策】SSRとCSRで処理を分けるCopyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
SSR/CSRに応じたfetch最適化Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
その他TIPS• ChromeのAuditでパフォーマンス測定する場合はシークレットモードで⾏う。通常のモードで⾏うと、インストールしているChrome拡張が邪魔して、スコアに影響することがある。– 実⾏後にこれが出てたら要注意。シークレットモードでやり直そう。Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
今後のパフォーマンス関連の展望• 定期的にパフォーマンスを計測する仕組みづくり– バンドルファイルサイズの可視化をCI/CDに組み込む– フロントエンドの各指標を可視化する仕組みづくりCopyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
最後に1つだけ…Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
パーソルキャリアでは⼀緒に働く仲間を募集しています︕Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.
終Copyright © PERSOL CAREER Co., Ltd. All Rights Reserved.