Slide 1

Slide 1 text

mercari x merpay Frontend Tech Talk #4 Yutaka Sasaki Pros and Cons of SSR and JAMstack

Slide 2

Slide 2 text

Yutaka Sasaki Github: sskyu Twitter: @_sskyu Joined on 2018/09/01 2 Profile

Slide 3

Slide 3 text

8月 本番環境の構築 一部のキャンペーンのみ JAMstack環 境に移行する 12月 キャンペーンMS 高速化の調査 本番リリース 9, 10月 全体アーキテクチャの設計 既存のキャンペーンを JAMstack で動かせるようにする 設計, JAMstack化 11月 devでキャンペーンの動作確認 他マイクロサービスに 実装の依頼 3 Performance improvement schedule どういうアプローチで高速化を図 るか方向性を決める

Slide 4

Slide 4 text

What is Merpay Campaign Pages 01 SSR Performance 02 Nuxt Generate 03 Migrate the cashless campaign to JAMstack 04 SSR vs JAMstack 05 4 Agenda

Slide 5

Slide 5 text

What is Merpay Campaign Pages

Slide 6

Slide 6 text

Merpay campaign pages

Slide 7

Slide 7 text

Technical stack of merpay frontend micro services Application CI / CD Infra Monitoring

Slide 8

Slide 8 text

SSRのパフォーマンスがでない 01 1Pod あたり 20rps しか捌けない(※2019/04時点、2019/08 では 90rps) スケールアウトさせて 40 ~ 80 Pod デプロイして捌いている とてもコスパが悪い 8 Issue

Slide 9

Slide 9 text

SSR Performance

Slide 10

Slide 10 text

いろいろなパターンで負荷試験をしてみた 1. Plain Nuxt App with express 2. campaign A (コンテンツ少) 3. campaign B(コンテンツ多) 4. campaign B(全体を client-only tag で囲む) 5. campaign B(ファーストビュー以外を client-only tag で囲む) 10 Load testing

Slide 11

Slide 11 text

Results of load testing Machine: Macbook Pro (15-inch 2018) Tool: https://github.com/tsenart/vegeta duration is 30sec, response time is less than 3 sec, average of 3 times

Slide 12

Slide 12 text

コンポーネント数 01 02 03 SSR するコンポーネント数に比例してパフォーマンスが落ちるのがわかった client-only tag SSR しない範囲を決めることで負荷を減らすことができる FirstView だけ SSR して、スクロールしないと見えない部分は client-only で囲むのが良さそう 限界が見える client-only tag を使うことで数割の改善は見込めるが、飛躍的な改善は難しそう 12 Summary of load testing

Slide 13

Slide 13 text

nuxt generate ならどうだろう?

Slide 14

Slide 14 text

nuxt generate (JAMstack)

Slide 15

Slide 15 text

What is nuxt generate Nuxt.js srcDir/pages/**/*.vue が RouteComponent になる e.g. src/pages/foo.vue → http://localhost:3000/foo src/pages/bar/index.vue → http://localhost:3000/bar nuxt generate SSR時に出力している RouteComponent の html を予め 生成する e.g. dist/foo/index.html dist/bar/index.html 15 https://ja.nuxtjs.org/guide/

Slide 16

Slide 16 text

susumerpay campaign

Slide 17

Slide 17 text

susumerpay campaign PC WebView on Mercari App Android iOS

Slide 18

Slide 18 text

nuxt generate 時に userAgent が取れない ・req.headers & navigator.userAgent が取得できない ・v-if の条件式に UA を入れると DOM が生成されずブラウザ実行時にエラー 18 Try nuxt generate Release hook nuxt generate rsync html js css css js html running in browsers

Slide 19

Slide 19 text

開発中のキャンペーンを本番に出ないようにする ・元々 middleware で実装されていた  → Incomming Request の度にハンドルする方式。nuxt generate では使えない ・nuxt-generate 用の module を独自に作って対応した  ① nuxt.config で 除外したいキャンペーン一覧を定義する  ② 'build:extendRoutes’ を hook して Routing から除外する  ③ ‘generate:done’ を hook して assets の中から除外したいキャンペーンの asset を削除する 19 Try nuxt generate

Slide 20

Slide 20 text

いくつかの nuxt lifecycle がブラウザ上で使えない ・middleware や fetch は nuxt generate 時に実行される  → ブラウザ上で実行されない ・fetch  → CI 上で API が叩かれる  → キャンペーンの場合はユーザーステータスを取得する API を叩く    → ページがブラウザにロードされてから API を叩くように変更した 20 Try nuxt generate

Slide 21

Slide 21 text

JAMstack での開発とデプロイフロー ・ローカル  → 普段通り nuxt dev (mode: universal) で開発する ・dev  → branch を push すると dev 用の GCS バケットに nuxt generate したものをデプロイする  → PullRequest に確認用の URL が貼られ、コードレビュー前に確認できる ・test  → master ブランチの内容が常にデプロイされる ・production  → release tag が打たれると本番にデプロイされる 21 About development experience

Slide 22

Slide 22 text

Migrate the cashless campaign to JAMstack

Slide 23

Slide 23 text

キャッシュレスキャンペーン ・シンプルなLP  → API を叩く箇所はない ・キャンペーン期間が 2019/10/01 ~ 2020/06/30 と長い ・先行して JAMstack 環境に移行する ・問題なく運用できそうであれば、  以降の新規キャンペーンは JAMstack 環境で開発する 23 What is the cashless campaign

Slide 24

Slide 24 text

JAMstack の本番環境を作る 01 02 03 ドメインを決めて MicroService 版と JAMstack 版のキャッシュレスキャンペーンを 2 箇所で動かす。IP制 限を掛けて社内からのみアクセス可能にする。 本番環境にキャッシュレスキャンペーンをデプロイする 本番デプロイの検証とMicroService版のキャッシュレスキャンペーンと差異がないことを保証する。 本番環境の有効化 IP制限を解除する。 導線を変更して JAMstack 版キャッシュレスキャンペーンにリクエストを流す。 24 How to migrate the cashless campaign

Slide 25

Slide 25 text

imag es css Architectures MicroService iOS Android PC WebView merpay gateway merpay api merpay campaign web merpay gateway merpay api cache static assets e.g. js, css, images handle API Requests handle static assets handle HTML and API Requests nuxt build create docker image nuxt generate deploy to GCS JAMstack html js html js css img

Slide 26

Slide 26 text

path の先頭に s/ がついている方を JAMstack 版にする ・MicroService 版  https://campaign.merpay.com/jp/2019-10-cashless/ ・JAMstack 版  https://campaign.merpay.com/s/jp/2019-10-cashless/ ※ s/ はそのうち外す予定 26 A new domain for campaign-web

Slide 27

Slide 27 text

s/ 配下で動くようにした影響で nuxt core file や画像の参照できない ・nuxt.config の router.base に /s/ を設定する  → 内に が埋め込まれる ・絶対パスで参照している箇所を相対パスにする 27 tag

Slide 28

Slide 28 text

Migration complete SSR JAMstack

Slide 29

Slide 29 text

SSR vs JAMstack

Slide 30

Slide 30 text

https://developers.google.com/web/updates/2019/02/rendering-on-the-web 30 Rendering on the Web

Slide 31

Slide 31 text

SSR コードで表現できることの自由度が高い node.js まわりの機能を追加することができる 運用コストが高い  → オンコール体制が必要  → rps が出ないのでスケールアウトで対応   せざるおえない JAMstack 運用コストが低い  → MicroService と比べて 1/10 に削減できそう  → オンコール体制が不要 LP のようなペライチのサイトには適している 管理画面のようなサイトには不向き 制約が多く、SSR のときと同等の表現をするとき   に工夫が必要  → ユーザー情報を取得する様な API を叩く場合は     Client 側の JS 実行タイミングでやる 31 Pros and Cons

Slide 32

Slide 32 text

32