Slide 1

Slide 1 text

0 ジャムジャム!!Jamstack_2 70万通りのURLを持つWebサービスを Next.jsにリプレイスして⾼速化した話

Slide 2

Slide 2 text

1 © 2021 Ateam Inc. 1 Uejima Aiji リードエンジニア@株式会社エイチームライフスタイル Twitter: aiji42_dev 8年のキャリアの中で、フロントエンジニアよりも バックエンドエンジニアとしてのキャリアのほうが長い (3:7くらい) でも最近はフロントエンドがメイン

Slide 3

Slide 3 text

2 © 2021 Ateam Inc. 2 今日はURLが膨大なサービスに Next.jsを導入した際の

Slide 4

Slide 4 text

3 © 2021 Ateam Inc. 3 立ちはだかった壁と その乗り越え方を紹介します

Slide 5

Slide 5 text

4 © 2021 Ateam Inc. 4 題材となるサービス

Slide 6

Slide 6 text

5 © 2021 Ateam Inc. 5 ライフエンディングに関する情報サイト 自分や家族にぴったりのお墓・霊園を探し、 資料請求をするサービス

Slide 7

Slide 7 text

6 © 2021 Ateam Inc. 6 トップ 記事 霊園詳細 1K Pages 700K Pages 30K Pages エントリー 霊園リスト&検索

Slide 8

Slide 8 text

7 © 2021 Ateam Inc. 7 トップ 記事 霊園リスト&検索 霊園詳細 1K Pages 700K Pages 30K Pages エントリー エリア(市区町村・駅)x霊園特徴(樹木葬, 納骨堂...etc.)

Slide 9

Slide 9 text

8 © 2021 Ateam Inc. 8 もともとはパフォーマンスが非常に悪かった

Slide 10

Slide 10 text

9 © 2021 Ateam Inc. 9 引用: https://addyosmani.com/blog/web-vitals-extension/

Slide 11

Slide 11 text

10 © 2021 Ateam Inc. 10 LCP (Largest Contentful Paint) CLS (Cumulative Layout Shift)

Slide 12

Slide 12 text

11 © 2021 Ateam Inc. 11 2020年 CoreWebVitalsをSEO評価に導入するとのアナウンスがあった https://developers.google.com/search/blog/2020/11/timing-for-page-experience

Slide 13

Slide 13 text

12 © 2021 Ateam Inc. 12 手を打つ必要があるということで

Slide 14

Slide 14 text

13 © 2021 Ateam Inc. 13 Next.jsを用いたJamstack化による CoreWebVitalsの改善を行った

Slide 15

Slide 15 text

14 © 2021 Ateam Inc. 14 その結果 大幅なパフォーマンス改善に成功!

Slide 16

Slide 16 text

15 © 2021 Ateam Inc. 15 LCP CLS

Slide 17

Slide 17 text

16 © 2021 Ateam Inc. 16 本題に入る前に

Slide 18

Slide 18 text

17 © 2021 Ateam Inc. 17 SSR / SG / ISR

Slide 19

Slide 19 text

18 © 2021 Ateam Inc. 18 この3つの用語を居酒屋を例にしておさらい

Slide 20

Slide 20 text

19 © 2021 Ateam Inc. 19 SSR (Server Side Rendering)

Slide 21

Slide 21 text

20 © 2021 Ateam Inc. 20 注文を受けて、 その都度ドリンクを注いで提供

Slide 22

Slide 22 text

21 © 2021 Ateam Inc. 21 時間はかかるがキンキンに冷えている (リアルタイム志向)

Slide 23

Slide 23 text

22 © 2021 Ateam Inc. 22 SG (Static Generate) (少し前まで SSG と呼ばれていた)

Slide 24

Slide 24 text

23 © 2021 Ateam Inc. 23 開店前にドリンクを作り置きしておく

Slide 25

Slide 25 text

24 © 2021 Ateam Inc. 24 提供は爆速 しかし鮮度は保証できない ※注文が入ってもストックの数は減らない

Slide 26

Slide 26 text

25 © 2021 Ateam Inc. 25 ISR (Incremental Static Regenerate)

Slide 27

Slide 27 text

26 © 2021 Ateam Inc. 26 作り置きするのはSGと同じ ドリンクを提供した際に 鮮度が落ちていたら次の注文に備えて作り直す

Slide 28

Slide 28 text

27 © 2021 Ateam Inc. 27 提供は爆速 注文頻度の高いメニューは鮮度良

Slide 29

Slide 29 text

28 © 2021 Ateam Inc. 28 今日お話するライフドットではISRを採用しています そしてVercelにデプロイしています

Slide 30

Slide 30 text

29 © 2021 Ateam Inc. 29 前提知識のインストールができたところで本題

Slide 31

Slide 31 text

30 © 2021 Ateam Inc. 30 70万通りのURLを持つサービスを Next.jsに導入する際の一番大きな壁

Slide 32

Slide 32 text

31 © 2021 Ateam Inc. 31 デプロイ時間

Slide 33

Slide 33 text

32 © 2021 Ateam Inc. 32 70万通りのページを生成するのにどれだけ時間がかかるか?

Slide 34

Slide 34 text

33 © 2021 Ateam Inc. 33 1ページ生成100msと仮定しても

Slide 35

Slide 35 text

34 © 2021 Ateam Inc. 34 約19時間半

Slide 36

Slide 36 text

35 © 2021 Ateam Inc. 35 デプロイで1日が終わってしまう

Slide 37

Slide 37 text

36 © 2021 Ateam Inc. 36 先程の居酒屋の例で解決策を探る

Slide 38

Slide 38 text

37 © 2021 Ateam Inc. 37 メニューが多い居酒屋はどうしているのか?

Slide 39

Slide 39 text

38 © 2021 Ateam Inc. 38 人気メニューや手間のかかるメニューは 作り置き(仕込みを)して

Slide 40

Slide 40 text

39 © 2021 Ateam Inc. 39 それ以外のメニューは 注文を受けてから作っている

Slide 41

Slide 41 text

40 © 2021 Ateam Inc. 40 実際のサービスに当てはめると

Slide 42

Slide 42 text

41 © 2021 Ateam Inc. 41 PV上位コンテンツをデプロイ時に生成し

Slide 43

Slide 43 text

42 © 2021 Ateam Inc. 42 それ以外はリクエストのタイミングで生成して 以降のリクエストはキャッシュを返却する

Slide 44

Slide 44 text

43 © 2021 Ateam Inc. 43 ということができればデプロイ時間を短縮できるし パフォーマンスも問題なさそう

Slide 45

Slide 45 text

44 © 2021 Ateam Inc. 44 ではNext.jsにおいてビルドするターゲットは何で決まるのか

Slide 46

Slide 46 text

45 © 2021 Ateam Inc. 45 getStaticPaths: SG/ISRのデプロイ時のビルドターゲット(パス)を決定する関数 返り値に fallback: true(or "blocking") を指定すると、 ビルドターゲットにないパスでリクエストを受けた際にビルドを行う。(遅延ビルド)

Slide 47

Slide 47 text

46 © 2021 Ateam Inc. 46 getStaticPathsの設定で 3種類のデプロイパータンを作ることができる

Slide 48

Slide 48 text

47 © 2021 Ateam Inc. 47 フルデプロイビルドパターン 全ページをデプロイ時にビルド • 全ページ一定のアクセス量があるページ群に有効 • BFFと通信してコンテンツを生成する場合、最大でも4桁程度のページ数が現実的 フルデプロイビルドパターン [slag].tsx PV 多 PV 少

Slide 49

Slide 49 text

48 © 2021 Ateam Inc. 48 フルリクエストビルドパターン デプロイ時のビルドを全スキップし、リクエスト時にビルド • デプロイは高速 <> 初アクセスはコンテンツを生成する分、多少TTFBが遅くなる • URLパターンがかけ合わせ等で指数関数的に増加するページ群に有効 フルリクエストビルドパターン product/[id]/sub.tsx PV 多 PV 少

Slide 50

Slide 50 text

49 © 2021 Ateam Inc. 49 ハイブリッドビルドパターン 一部のページをデプロイ時、それ以外をリクエスト時にビルド • アクセス数に偏りがあるページ群で強い効果を発揮 (例: 主要都市と地方) • デプロイ時間と相談しながらビルド対象数を選択する デプロイビルド リクエストビルド search/[prefecture]/[city]/[condition].tsx PV 多 PV 少

Slide 51

Slide 51 text

50 © 2021 Ateam Inc. 50 この3種類を適切に設定し

Slide 52

Slide 52 text

51 © 2021 Ateam Inc. 51 ライフドットでは全PVにおける6~7割が 初回アクセスでもビルド済みURLに到達できるようにした (※PVの分散は均一ではないことに注意)

Slide 53

Slide 53 text

52 © 2021 Ateam Inc. 52 記事 霊園リスト&検索 霊園詳細 フルデプロイビルド ハイブリッドビルド(単一条件) + フルリクエストビルド(掛合わせ条件) ハイブリッドビルド(メインページ) + フルリクエストビルド(サブページ)

Slide 54

Slide 54 text

53 © 2021 Ateam Inc. 53 デプロイに要する時間はこうなった

Slide 55

Slide 55 text

54 © 2021 Ateam Inc. 54 記事 霊園リスト&検索 霊園詳細 フルデプロイビルド ハイブリッドビルド(単一条件) + フルリクエストビルド(掛合わせ条件) ハイブリッドビルド(メインページ) + フルリクエストビルド(サブページ) 45分

Slide 56

Slide 56 text

55 © 2021 Ateam Inc. 55 しかし

Slide 57

Slide 57 text

56 © 2021 Ateam Inc. 56 Vercel(チームプラン)の パイプラインのタイムアウトは45分

Slide 58

Slide 58 text

57 © 2021 Ateam Inc. 57 45分の間にビルドだけでなく エッジへの配備まで完了させなければならない

Slide 59

Slide 59 text

58 © 2021 Ateam Inc. 58 ビルド時間の長さに比例してエラーの発生確率も上がる デプロイ終盤のエラー発生は辛いので 15分くらいでデプロイが完了できればなあ。。。

Slide 60

Slide 60 text

59 © 2021 Ateam Inc. 59 ならば さらにデプロイ時間を短縮!

Slide 61

Slide 61 text

60 © 2021 Ateam Inc. 60 さっきの居酒屋の例に話を戻そう

Slide 62

Slide 62 text

61 © 2021 Ateam Inc. 61

Slide 63

Slide 63 text

62 © 2021 Ateam Inc. 62

Slide 64

Slide 64 text

63 © 2021 Ateam Inc. 63 目的別でサービスを縦割りし それぞれのデプロイを独立して行うことで時間短縮

Slide 65

Slide 65 text

64 © 2021 Ateam Inc. 64 www.lifedot.jp Vercel ・・・ ・・・

Slide 66

Slide 66 text

65 © 2021 Ateam Inc. 65 product.vercel.lifedot.jp search.vercel.lifedot.jp article.vercel.lifedot.jp 目的別でサービスを縦割り

Slide 67

Slide 67 text

66 © 2021 Ateam Inc. 66 www.lifedot.jp /db/*/ /pref-*/city-*/*/ /pref-*/st-*/*/ /pref-*/cond-*/*/ /ohaka/[a-z]+/ product.vercel.lifedot.jp article.vercel.lifedot.jp search.vercel.lifedot.jp CDN (CloudFront) + エッジコンピューティング (LambdaEdge) で統合

Slide 68

Slide 68 text

67 © 2021 Ateam Inc. 67 この構成でTTFBは50ms~100ms強 ※通信環境によって多少異なる ※それぞれ計測しているページは別(無作為に選別)

Slide 69

Slide 69 text

68 © 2021 Ateam Inc. 68 十分な速度が出ている (Googleは200msを下回ること推奨している)

Slide 70

Slide 70 text

69 © 2021 Ateam Inc. 69 そして肝心なビルド時間は

Slide 71

Slide 71 text

70 © 2021 Ateam Inc. 70 記事 霊園リスト&検索 霊園詳細 15分 15分 15分 それぞれ並行してビルドされるので 15分に短縮

Slide 72

Slide 72 text

71 © 2021 Ateam Inc. 71 🎉

Slide 73

Slide 73 text

72 © 2021 Ateam Inc. 72 そもそもどうやってサービスのコードを分割するのか?

Slide 74

Slide 74 text

73 © 2021 Ateam Inc. 73 一部分の変更で 全体のデプロイが実行されるのは効率が悪い

Slide 75

Slide 75 text

74 © 2021 Ateam Inc. 74 リポジトリを分ける? 共有レイアウト・コンポネントはどうする?

Slide 76

Slide 76 text

75 © 2021 Ateam Inc. 75 開発も効率化したい!

Slide 77

Slide 77 text

76 © 2021 Ateam Inc. 76 Nxでのモノレポ戦略を採用

Slide 78

Slide 78 text

77 © 2021 Ateam Inc. 77 NxとはJSベースのモノレポ用開発ツール

Slide 79

Slide 79 text

78 © 2021 Ateam Inc. 78 特徴

Slide 80

Slide 80 text

79 © 2021 Ateam Inc. 79 Storybook, Cypress, Jest, ESLint などが標準配備される テストを書く文化を浸透させやすい https://nx.dev

Slide 81

Slide 81 text

80 © 2021 Ateam Inc. 80 package.json と node_modules がリポジトリに1つなので 依存パッケージのアップデートなどバージョン管理が楽 ※よく比較にあがる lerna などはルートと各appごとに発生する (ただし志向や用途が違うので単純比較していいものではない)

Slide 82

Slide 82 text

81 © 2021 Ateam Inc. 81 vs code や IntelliJ用の公式プラグインがあり クリックでビルド&サーブしたりテスト実行できる 複雑なコマンド学習をメンバーに強要しなくて良い

Slide 83

Slide 83 text

82 © 2021 Ateam Inc. 82 appsとlibsが基本構造 共通モジュールはlibsに配備 自動的にプロジェクト名でエイリアスされる 無意識的にnpmモジュールライクな参照が可能 import { Header } "@lifedot/components" import { useStockList } "@lifedot/hooks" libs apps article search product components relay(graphql) hooks, router, layouts, ...etc. @lifedot/components

Slide 84

Slide 84 text

83 © 2021 Ateam Inc. 83 apps article search product product.vercel.lifedot.jp search.vercel.lifedot.jp article.vercel.lifedot.jp Vercel の "Ignored Build Step" と組み合わせることで 変更が生じたappsのみデプロイできる ❌ ❌ update

Slide 85

Slide 85 text

84 © 2021 Ateam Inc. 84 各PJが独立して15分でデプロイが可能 & プロジェクトを絞ってデプロイできるようになった

Slide 86

Slide 86 text

85 © 2021 Ateam Inc. 85 🎉

Slide 87

Slide 87 text

86 © 2021 Ateam Inc. 86 今日紹介したこと

Slide 88

Slide 88 text

87 © 2021 Ateam Inc. 87 1. 3パターンのデプロイ方法と遅延ビルドの活用 • フルデプロイビルド • フルリクエストビルド • ハイブリッドビルド 2. サービスの縦割りと CDN+エッジコンピューティングによる統合 3. Nxによるリポジトリのモノレポ化

Slide 89

Slide 89 text

88 © 2021 Ateam Inc. 88 今日紹介しきれなかったこと

Slide 90

Slide 90 text

89 © 2021 Ateam Inc. 89 1. バンドルサイズの削減格闘記 2. 効率の良いキャッシュを目指した変動 revalidate 3. GraphQLによるパフォーマンス改善の話

Slide 91

Slide 91 text

90 © 2021 Ateam Inc. 90 またの機会にお話させていただきます

Slide 92

Slide 92 text

91 © 2021 Ateam Inc. 91 ご質問やもっと詳しく聞きたい方は Twitter でどうぞ! @aiji42_dev

Slide 93

Slide 93 text

92 ITにできることを、次々と。