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

Pocochaにおけるフロントエンドの領域とアーキテクチャ変遷【DeNA TechCon 2021 Summer】/techcon2021summer-05

Pocochaにおけるフロントエンドの領域とアーキテクチャ変遷【DeNA TechCon 2021 Summer】/techcon2021summer-05

Pocochaの成長とともに、採用技術も幾度となく変化してきました。中でも流れの速いフロントエンド領域では、フレームワークの乗り換え・アーキテクチャの変更・インフラの移行と大きな変化を経てきています。

それぞれのフェーズにおいてどのような判断の元で次のステップへ移ったのか、そしてどのような反省が生まれたのか、その変遷についてご紹介いたします。

DeNA_Tech

June 29, 2021
Tweet

More Decks by DeNA_Tech

Other Decks in Technology

Transcript

  1. 自己紹介 • 菰原 裕 / Yu Komohara • 2018年DeNA新卒入社 ◦

    Pococha事業部 システム部 ◦ イベントチームでバックエンド開発 ◦ その後Webチームでフロントエンド開発 ▪ Rails, React, Next.js, ... 2
  2. Webで実装する意味 • 企画の PDCA・仮説検証が回しやすい(主にWeb版) ◦ 本番反映や取り下げが容易 ◦ ネイティブのリリースサイクルに影響されない (Pococha なら二週間に一回)

    • iOS, Android の両方で WebView さえ用意してあげれ ばクロスプラットフォーム • エンジニアリソースを有効活用できる 17
  3. 初期(2017/1〜2018/11) • Rails が API サーバと Web サーバの両方の役割を担う • 試行錯誤をしていた段階で、ページごと(イベントはイベントごと)

    にUIが異なり、マスターデータを元に動的にページを生成できない • ページ数が少ないので、なんとかコピペ運用で回せていた時期 23
  4. 当時(2018年夏頃)検討された選択肢 • Angular ◦ 半年に一度の破壊的なメジャーアップデート • React + React Helmet

    ◦ webpack や Babel や Express を自前で入れて管理する必要がある • Vue + Nuxt.js • React + Next.js 34
  5. 当時(2018年夏頃)検討された選択肢 • Angular ◦ 半年に一度の破壊的なメジャーアップデート • React + React Helmet

    ◦ webpack や Babel や Express を自前で入れて管理する必要がある • Vue + Nuxt.js ◦ SSR (後述)は出来るが、当時(Vue 2)ビューにロジックを含めたくなかった • React + Next.js 35
  6. 当時(2018年夏頃)検討された選択肢 • Angular ◦ 半年に一度の破壊的なメジャーアップデート • React + React Helmet

    ◦ webpack や Babel や Express を自前で入れて管理する必要がある • Vue + Nuxt.js ◦ SSR (後述)は出来るが、当時(Vue 2)ビューにロジックを含めたくなかった • React + Next.js ◦ 自前でビルド周りやサーバを整備する必要がない。SSR が容易に行える 36
  7. 移行ステップ • React + Next.js のプロジェクトを立ち上げる ◦ ページを作る ◦ 認証機構を実装する

    ◦ デプロイフローを整える • フロント側にデータを渡す仕組みを作る ◦ データフォーマットを定める(csv, yaml) ◦ API を Rails に生やす 37
  8. 事業拡大に伴う課題(再掲) • 自動化されても辛いコピペ運用 ◦ API 側にマスターデータを保持してページに流し込む形式 • LP のような、フロントで完結するページを Rails

    で作るのが辛い ◦ LP を Rails に載せる必要がなくなった • リッチな UI を JS でゴリゴリ書きたい ◦ Rails の制約がないので好きに書ける 45
  9. SSR(Server Side Rendering) 1. ユーザがリクエストを送る 2. リクエストが到達した段階で、サーバ側で JS が実行される 3.

    初期表示用のページ(First View)をレンダリングして、レスポンス が返る 4. その後必要に応じてクライアント側でも JS が実行され、最終的な ページが表示される 51
  10. SSR のメリット • UX 向上 ◦ 初回レンダリングがブラウザではなくサーバで行われるので、高速 ◦ ブラウザでの JS

    の実行を待たずに描画されるため、空白ページやインジ ケータが表示されない 53
  11. SSR のメリット • UX 向上 ◦ 初回レンダリングがブラウザではなくサーバで行われるので、高速 ◦ ブラウザでの JS

    の実行を待たずに描画されるため、空白ページやインジ ケータが表示されない • SEO ◦ 必要な情報をサーバ側でレンダリングした上でレスポンスが返るので /users/[userId] のような動的なルーティングでも OGP を設定できる ◦ クローラに関しては、レンダリングのタイムラグ以外は問題ない 54
  12. SSR のデメリット • 自前で導入するのは難しい ◦ フレームワークに依存することになる • コードが煩雑になる ◦ Next.js(当時は

    9.1.6) では getInitialProps という SSR でも CSR で も呼ばれるライフサイクルがあり、Universal JS を意識する必要があっ た 57
  13. SSR のデメリット • 自前で導入するのは難しい ◦ フレームワークに依存することになる • コードが煩雑になる ◦ Next.js(当時は

    9.1.6) では getInitialProps という SSR でも CSR で も呼ばれるライフサイクルがあり、Universal JS を意識する必要があっ た ◦ SSR はサーバ側(Node 環境)で実行されシングルスレッドで動作し、シ ングルスレッドで固有の問題も生じうる 58
  14. getStaticProps の登場 • Next.js 9.3(2020/3)から追加された、SSG(Static Site Generation) 時に 実行されるライフサイクル •

    SSG 自体は一般的な方式であり、 SSR と異なりサーバ側で事前にビルドされた 静的コンテンツが返るので、レスポンスが早い 62
  15. getStaticProps の登場 • Next.js 9.3(2020/3)から追加された、SSG(Static Site Generation) 時に 実行されるライフサイクル •

    SSG 自体は一般的な方式であり、 SSR と異なりサーバ側で事前にビルドされた 静的コンテンツが返るので、レスポンスが早い • Next.js にも静的に書き出す機能や自動的に SSG される機構が存在したが、9.3 で専用のライフサイクルが登場した 63
  16. getStaticProps の登場 • Next.js 9.3(2020/3)から追加された、SSG(Static Site Generation) 時に 実行されるライフサイクル •

    SSG 自体は一般的な方式であり、 SSR と異なりサーバ側で事前にビルドされた 静的コンテンツが返るので、レスポンスが早い • Next.js にも静的に書き出す機能や自動的に SSG される機構が存在したが、9.3 で専用のライフサイクルが登場した • 動的ページで SSG を実装するための getStaticPaths というライフサイクルも 同時に登場 64
  17. getStaticProps の登場 • Next.js 9.3(2020/3)から追加された、SSG(Static Site Generation) 時に 実行されるライフサイクル •

    SSG 自体は一般的な方式であり、 SSR と異なりサーバ側で事前にビルドされた 静的コンテンツが返るので、レスポンスが早い • Next.js にも静的に書き出す機能や自動的に SSG される機構が存在したが、9.3 で専用のライフサイクルが登場した • 動的ページで SSG を実装するための getStaticPaths というライフサイクルも 同時に登場 • Vercel へのデプロイ時、条件を満たすページは自動で SSG を行って CDN へ展 開してくれるなど、SSG のサポートは強力 65
  18. SSGの実装 • www.example.com/entries のような一 覧ページ • ビルド時に getStaticProps が実行さ れ、一覧情報が

    API から取得される • getStaticProps の return がコンポーネ ントへ渡され、APIで取得した情報を元に 事前にビルドされる 68
  19. SSGの実装(動的ルーティング) • www.example.com/entries/[entryId] のような詳細ページ • getStaticPaths で、事前にどの ID の ページについて

    SSG するかを指定する • それぞれのページについて、ページ内容を getStaticProps で API から取得する 71
  20. SSGの実装(動的ルーティング) • www.example.com/entries/[entryId] のような詳細ページ • getStaticPaths で、事前にどの ID の ページについて

    SSG するかを指定する • それぞれのページについて、ページ内容を getStaticProps で API から取得する • getStaticProps の return がコンポーネ ントへ渡され、getStaticPaths で指定し た全てのパスについて事前ビルドが行われ る 72
  21. 74

  22. 75

  23. ISG(Incremental Static Generation) • getStaticProps 等と同じく Next.js 9.3(2020/3)で追加 • getStaticPaths

    で fallback を false 以外に指定した場合に有効化 • 事前ビルドしていないページへリクエストが到達した段階でインクリ メンタルに SSG を実行し、以後そのページへのリクエストには SSG されたコンテンツが返る 76
  24. ISR(Incremental Static Regeneration) • Next.js 9.5(2020/7)で追加 • getStaticProps の return

    で revalidate を指定した場合に有効化 • revalidate で指定した秒数の経過後、新しいリクエストが来たら、再度 SSG を実行す る(= キャッシュを更新する) 79
  25. アーキテクチャ移行の2つの壁 [1/2] • インフラの移行 ◦ Function 数問題 ▪ もともとは Serverless

    Framework を使って Lambda の一関数に プロジェクトを丸ごとデプロイしていた 85
  26. アーキテクチャ移行の2つの壁 [1/2] • インフラの移行 ◦ Function 数問題 ▪ もともとは Serverless

    Framework を使って Lambda の一関数に プロジェクトを丸ごとデプロイしていた ▪ Vercel へデプロイすると、SSR をするエンドポイントごと(page ごと)に関数が分割される 86
  27. アーキテクチャ移行の2つの壁 [1/2] • インフラの移行 ◦ Function 数問題 ▪ もともとは Serverless

    Framework を使って Lambda の一関数に プロジェクトを丸ごとデプロイしていた ▪ Vercel へデプロイすると、SSR をするエンドポイントごと(page ごと)に関数が分割される ▪ Vercel の Pro プランではエンドポイント数は上限が 24 ……移行が 決まった段階で、エンドポイント数は約 40 …… 87
  28. アーキテクチャ移行の2つの壁 [1/2] • インフラの移行 ◦ Function 数問題 ▪ もともとは Serverless

    Framework を使って Lambda の一関数に プロジェクトを丸ごとデプロイしていた ▪ Vercel へデプロイすると、SSR をするエンドポイントごと(page ごと)に関数が分割される ▪ Vercel の Pro プランではエンドポイント数は上限が 24 ……移行が 決まった段階で、エンドポイント数は約 40 …… ▪ 上記はあくまで SSR が必要なエンドポイントの数であり、SSG さ れるページは含まれない 88
  29. アーキテクチャ移行の2つの壁 [1/2] • インフラの移行 ◦ Function 数問題 ▪ もともとは Serverless

    Framework を使って Lambda の一関数に プロジェクトを丸ごとデプロイしていた ▪ Vercel へデプロイすると、SSR をするエンドポイントごと(page ごと)に関数が分割される ▪ Vercel の Pro プランではエンドポイント数は上限が 24 ……移行が 決まった段階で、エンドポイント数は約 40 …… ▪ 上記はあくまで SSR が必要なエンドポイントの数であり、SSG さ れるページは含まれない • コードを先に修正してから Vercel へ移行する必要がある 89
  30. アーキテクチャ移行の2つの壁 [1/2] • インフラの移行 ◦ 250MB問題 ▪ 当時使用していた Next.js のバージョンは

    9.1.6 で、SSG や ISR を 使うためにアップデートが必要 ▪ Lambda へデプロイするパッケージの容量の上限は 250MB で、 Next.js をアップデートすると超過することが発覚 92
  31. アーキテクチャ移行の2つの壁 [1/2] • インフラの移行 ◦ 250MB問題 ▪ 当時使用していた Next.js のバージョンは

    9.1.6 で、SSG や ISR を 使うためにアップデートが必要 ▪ Lambda へデプロイするパッケージの容量の上限は 250MB で、 Next.js をアップデートすると超過することが発覚 • Vercel へ先に移行してからコードを修正する必要がある 93
  32. アーキテクチャ移行の2つの壁 [1/2] • インフラの移行 ◦ Function 数問題 → Vercel へ移行するには

    SSG, ISR のコードに変える必要がある ◦ 250MB問題 → SSG, ISR のコードに変えるには Vercel へ移行する必要がある 95
  33. アーキテクチャ移行の2つの壁 [1/2] • インフラの移行 ◦ Function 数問題 → Vercel へ移行するには

    SSG, ISR のコードに変える必要がある ◦ 250MB問題 → SSG, ISR のコードに変えるには Vercel へ移行する必要がある Vercel の Pro プランで運用するには、インフラ移行と アーキテクチャ移行(Next.jsのアプデを含む)を同時 に行う必要がある → 96
  34. アーキテクチャ移行の2つの壁 [1/2] • インフラの移行 ◦ 補足 ▪ Vercel の Pro

    プランの上限の中でやりくりしようとした結果複雑な ことになったが、実は2020年秋ごろに Hobby プラン以外は上限が 撤廃されたらしい ▪ 事業のさらなる拡大により、Enterprise プランでないと帯域幅の上 限に引っかかることとなりました 100
  35. アーキテクチャ移行の2つの壁 [2/2] • コードの大幅な変更 ◦ getInitialProps の廃止 ▪ コンポーネントのレンダリング時にリクエストを投げる CSR

    方式へ移行 ◦ OGP が必要なページは getStaticProps を使用 ◦ OGP が必要な動的ページは getStaticProps + getStaticPaths による ISR 104
  36. アーキテクチャ移行の2つの壁 [2/2] • コードの大幅な変更 ◦ getInitialProps の廃止 ▪ コンポーネントのレンダリング時にリクエストを投げる CSR

    方式へ移行 ◦ OGP が必要なページは getStaticProps を使用 ◦ OGP が必要な動的ページは getStaticProps + getStaticPaths による ISR ◦ その他、getInitialProps を前提に書かれた HOC の廃止も…… 105
  37. その他色々な変遷 • Hooks 導入 ◦ クラスコンポーネントの撲滅 • Redux → Recoil

    ◦ Hooks や非同期処理との相性を考えて移行中 • LPを爆速で作れる仕組み ◦ Pococha の LP を支える技術 - DeNA Design ◦ Figma プラグインを作って Pococha の LP 実装をほぼ自動化した · DeNA Engineers' Blog 108
  38. あるべき姿に向けて • レポジトリの分割 ◦ コード修正時に影響範囲を限定できる & QA工数の削減 • Vercel のプロジェクト運用を整備したい

    ◦ レポジトリ連携が出来ないので、開発環境のドメインの数だけプロジェクトが 乱立している ◦ レポジトリ連携が GH:E 対応したら、ひとつのプロジェクトへまとめたい 112
  39. あるべき姿に向けて • レポジトリの分割 ◦ コード修正時に影響範囲を限定できる & QA工数の削減 • Vercel のプロジェクト運用を整備したい

    ◦ レポジトリ連携が出来ないので、開発環境のドメインの数だけプロジェクトが 乱立している ◦ レポジトリ連携が GH:E 対応したら、ひとつのプロジェクトへまとめたい • 技術的負債の排除 ◦ Rails に残っている Web ページの移行 ◦ クラスコンポーネントの撲滅 113
  40. あるべき姿に向けて • レポジトリの分割 ◦ コード修正時に影響範囲を限定できる & QA工数の削減 • Vercel のプロジェクト運用を整備したい

    ◦ レポジトリ連携が出来ないので、開発環境のドメインの数だけプロジェクトが 乱立している ◦ レポジトリ連携が GH:E 対応したら、ひとつのプロジェクトへまとめたい • 技術的負債の排除 ◦ Rails に残っている Web ページの移行 ◦ クラスコンポーネントの撲滅 • まだまだやりたいことがある ◦ 新機能開発, 各工程での効率化, etc... 114
  41. まとめ • Pocochaにおけるフロントエンドの領域 ◦ WebView, Web版, 公式サイト等、多岐にわたる • Pocochaにおけるフロントの歴史 フレームワーク移行

    ◦ 事業拡大に耐えうるフレームワークへ • Pocochaにおけるフロントの歴史 インフラ・アーキテクチャ変更 • 展望 118
  42. まとめ • Pocochaにおけるフロントエンドの領域 ◦ WebView, Web版, 公式サイト等、多岐にわたる • Pocochaにおけるフロントの歴史 フレームワーク移行

    ◦ 事業拡大に耐えうるフレームワークへ • Pocochaにおけるフロントの歴史 インフラ・アーキテクチャ変更 ◦ 技術的負債を残さない開発へ • 展望 119
  43. まとめ • Pocochaにおけるフロントエンドの領域 ◦ WebView, Web版, 公式サイト等、多岐にわたる • Pocochaにおけるフロントの歴史 フレームワーク移行

    ◦ 事業拡大に耐えうるフレームワークへ • Pocochaにおけるフロントの歴史 インフラ・アーキテクチャ変更 ◦ 技術的負債を残さない開発へ • 展望 ◦ 健全な体制で、Web ならではの価値を提供 120
  44. 121