Upgrade to Pro — share decks privately, control downloads, hide ads and more …

VercelとNext.jsの機能を最大限に活用したA/Bテスト手法

 VercelとNext.jsの機能を最大限に活用したA/Bテスト手法

AijiUejima

April 21, 2023
Tweet

More Decks by AijiUejima

Other Decks in Technology

Transcript

  1. © 2023 Ateam Inc.
    VercelとNext.jsの機能を
    最大限に活用したA/Bテスト手法
    Serverless Frontend Meetup #2

    View Slide

  2. © 2023 Ateam Inc.
    自己紹介
    Who am I ?
    Name: Aiji Uejima
    Twitter: aiji42_dev
    Github: aiji42
    株式会社エイチームライフデザイン
    技術開発室所属 リードエンジニア
    最近興味があるのはエッジランタイム。
    2

    View Slide

  3. © 2023 Ateam Inc.
    A/Bテストやってますか?
    3

    View Slide

  4. © 2023 Ateam Inc.
    A/Bテストの概要
    機能やデザインなどを出し分け、どちらが優れているかを検証する手法
    4
    A B
    VS

    View Slide

  5. © 2023 Ateam Inc.
    Next.jsでA/Bテストする時ってどうしてる?
    5

    View Slide

  6. © 2023 Ateam Inc.
    Next.jsでのA/Bテストのやり方
    コンポーネントベース(クライアントサイド)
    レンダリング時に何らかのロジックを使って、オリジナル(A)とチャレンジャー(B)を出し分ける
    ※Cookie等でA/Bどちらに振ったかをスティッキー(固定化)する必要が別途必要
    6

    View Slide

  7. © 2023 Ateam Inc.
    チャレンジャー(B)のコードが
    バンドルされてしまう
    7

    View Slide

  8. © 2023 Ateam Inc.
    チャレンジャー(B)用のページファイルを複製しておいて、Next.js v12から導入されたmiddlewareでパスをリライトする。
    Next.jsでのA/Bテストのやり方
    ルーティングベース(ファイルシステム)
    8
    /pages/foo.tsx
    /pages/foo-2.tsx
    middleware.ts でパスをリライト
    h"ps://exmple.dev/foo

    View Slide

  9. © 2023 Ateam Inc.
    一見良さそうだが
    ページを複製して管理する必要がある
    9

    View Slide

  10. © 2023 Ateam Inc.
    A/Bテストの課題あるある
    10

    View Slide

  11. © 2023 Ateam Inc.
    動いているのか動いていないのか
    不明なチャレンジャーコードがいつまでも残る🫥
    11

    View Slide

  12. © 2023 Ateam Inc.
    振り分けを考慮しないといけないので
    テストが複雑になる🤯
    12

    View Slide

  13. © 2023 Ateam Inc.
    このようにチャレンジャーが
    ブランチ内で共存すると管理が煩雑になっていく
    13

    View Slide

  14. © 2023 Ateam Inc.
    このようにチャレンジャーが
    ブランチ内で共存すると管理が煩雑になっていく
    14

    View Slide

  15. © 2023 Ateam Inc.
    ブランチ・デプロイベースでA/Bテストしよう🚀
    15

    View Slide

  16. © 2023 Ateam Inc.
    ブランチベースのA/Bテスト
    オリジナルとチャレンジャーのブランチを分けてA/Bする
    16
    origin/main origin/challenger-1

    View Slide

  17. © 2023 Ateam Inc.
    ブランチベースのA/Bテスト
    オリジナルとチャレンジャーのブランチを分けてA/Bする
    17
    https://exmple.dev/foo

    View Slide

  18. © 2023 Ateam Inc.
    こうすればチャレンジャーのコードが
    mainブランチに紛れることは一切ない
    18

    View Slide

  19. © 2023 Ateam Inc.
    結果が良ければブランチをマージ
    結果が悪ければブランチを破棄
    19

    View Slide

  20. © 2023 Ateam Inc.
    テストもそれぞれで独立してできるので
    振り分けを考慮しなくて良い
    20

    View Slide

  21. © 2023 Ateam Inc.
    どうやって
    別ブランチのリソースにアクセスさせれば…?🧐
    21

    View Slide

  22. © 2023 Ateam Inc.
    Vercelには
    プレビューデプロイがあるじゃないか💡
    22

    View Slide

  23. © 2023 Ateam Inc. 23
    通常通りオリジナルをVercelにデプロイする
    deploy🚀
    example.vercel.app

    View Slide

  24. © 2023 Ateam Inc. 24
    続いてチャレンジャー用のブランチを切って開発する
    example.vercel.app
    example.vercel.app

    View Slide

  25. © 2023 Ateam Inc. 25
    プッシュした途端にVercelでプレビューデプロイが始まる
    deploy🚀
    example.vercel.app
    example.vercel.app example-b.vercel.app

    View Slide

  26. © 2023 Ateam Inc. 26
    プロダクション(main)のドメインにアクセスしたときに...
    example.vercel.app
    example.vercel.app
    example-b.vercel.app
    (preview)

    View Slide

  27. © 2023 Ateam Inc. 27
    middlewareでインターセプトして...
    example.vercel.app
    example.vercel.app
    example-b.vercel.app
    (preview)

    View Slide

  28. © 2023 Ateam Inc. 28
    A/Bで振り分けてプレビューデプロイ用のドメインにプロキシする
    example.vercel.app
    example.vercel.app
    example-b.vercel.app
    (preview)
    middleware内でのリライトはクロスオリジンに対しても可能

    View Slide

  29. © 2023 Ateam Inc.
    気をつけなければいけないポイント
    29

    View Slide

  30. © 2023 Ateam Inc.
    ①アセットとNextImageのオリジン
    30

    View Slide

  31. © 2023 Ateam Inc.
    チャレンジャー用のアセットはオリジナルのドメインにリクエストしても存在しない
    (ハッシュが付与されるので同一のアセットは存在しない)
    チャレンジャーのオリジンに直接リクエストしなければならない
    31
    アセットは直接チャレンジャーのオリジンにリクエストさせなければならない
    example.vercel.app
    example.vercel.app
    example-b.vercel.app
    (preview)
    /_next/static/chunks/pages/_app-bbb.js ❌

    /_next/staBc/chunks/pages/_app-bbb.js
    _app-aaa.js
    _app-bbb.js
    Current is B

    View Slide

  32. © 2023 Ateam Inc. 32
    next.config.jsでアセットのオリジンを指定してやる

    View Slide

  33. © 2023 Ateam Inc.
    ②ナビゲーション
    33

    View Slide

  34. © 2023 Ateam Inc. 34
    A/Bテスト対象外ページから対象内ページへのナビゲーションを考える
    /top /foo
    A/Bテスト対象外 A/Bテスト対象内

    View Slide

  35. © 2023 Ateam Inc.
    Next.jsではナビゲート時にナビゲート先のドキュメントをフルでリクエストするのではなく、
    ナビゲート先のページで使用するprops(json)をプリフェッチすることで高速にナビゲートしている。
    35
    Next.jsのナビゲーションに関して
    /_next/data/xxxxxx/foo.json
    example.vercel.app
    example.vercel.app

    View Slide

  36. © 2023 Ateam Inc. 36
    A/Bテスト対象外ページから対象内ページへのナビゲーションするときの問題
    /_next/data/hash-for-origin/foo.json
    example.vercel.app
    example.vercel.app
    🍪(challenger)
    🚫
    チャレンジャー用のクッキーを持っているので
    オリジナルのJSONは返却してはいけない
    example-b.vercel.app
    (preview)

    マニフェストファイルに従ってJSONをリクエスト
    するため、振り分けによらずオリジナルが要求される
    ハッシュが異なるのでチャレンジャーに
    プロキシしてもファイルは見つからない

    View Slide

  37. © 2023 Ateam Inc. 37
    A/Bテスト対象外ページから対象内ページへのナビゲーションするときの問題への対処
    /_next/data/aaaa/foo.json
    example.vercel.app
    example.vercel.app
    🍪(challenger)
    代わりに https://example-b.vercel.app/foo への
    リダイレクトステータスを返すとチャレンジャーへナビゲートされる

    View Slide

  38. © 2023 Ateam Inc.
    ここまでの話を踏まえると
    next.config.js と middleware が
    カオスになりそう...😫
    38

    View Slide

  39. © 2023 Ateam Inc.
    いろいろめんどくさいので
    ライブラリを作った✌
    39

    View Slide

  40. © 2023 Ateam Inc. 40
    next-with-split
    https://github.com/aiji42/next-with-split

    View Slide

  41. © 2023 Ateam Inc.
    実演🧪
    41

    View Slide

  42. © 2023 Ateam Inc. 42
    next-with-split
    - スティッキーセッションの期間の調整
    - A/B/C/…テスト
    - 振り分け率の調整
    実演では紹介しなかった機能
    今後のアップデート
    - Vercel Edge Configとの連携
    - デプロイしなくてもA/Bテストの開始・停止や設定等を調整できるように

    View Slide

  43. © 2023 Ateam Inc.
    A/Bテストの管理が面倒だなーと感じている人は
    ぜひ使ってみてください✌
    43

    View Slide

  44. © 2023 Ateam Inc.
    Bye👋
    44

    View Slide

  45. View Slide