Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
App Router時代のデータ取得アーキテクチャ
Search
uhyo
August 02, 2023
Programming
48
17k
App Router時代のデータ取得アーキテクチャ
2023-08-02 What's "Next" JS Meetup
uhyo
August 02, 2023
Tweet
Share
More Decks by uhyo
See All by uhyo
React 19時代のコンポーネント設計ベストプラクティス
uhyo
18
7.6k
型定義でAIと会話する:型を通じてAIに意図を伝えるテクニック
uhyo
1
33
タグ付きユニオン型を便利に使うテクニックとその注意点
uhyo
3
1k
ECMAScript仕様の最新動向: プロセスの変化と仕様のトレンド
uhyo
3
800
TypeScript 6.0で非推奨化されるオプションたち
uhyo
17
7.2k
Claude Code 10連ガチャ
uhyo
5
1k
AI時代、“平均値”ではいられない
uhyo
8
3.9k
意外と難しいGraphQLのスカラー型
uhyo
5
1k
RSCの時代にReactとフレームワークの境界を探る
uhyo
13
4.9k
Other Decks in Programming
See All in Programming
Takumiから考えるSecurity_Maturity_Model.pdf
gessy0129
1
120
オブザーバビリティ駆動開発って実際どうなの?
yohfee
3
690
ご飯食べながらエージェントが開発できる。そう、Agentic Engineeringならね。
yokomachi
1
280
Rubyと楽しいをつくる / Creating joy with Ruby
chobishiba
0
200
Claude Codeセッション現状確認 2026福岡 / fukuoka-aicoding-00-beacon
monochromegane
4
390
go directiveを最新にしすぎないで欲しい話──あるいは、Go 1.26からgo mod initで作られるgo directiveの値が変わる話 / Go 1.26 リリースパーティ
arthur1
2
470
CSC307 Lecture 14
javiergs
PRO
0
450
Python’s True Superpower
hynek
0
200
Go Conference mini in Sendai 2026 : Goに新機能を提案し実装されるまでのフロー徹底解説
yamatoya
0
520
PostgreSQL を使った快適な go test 環境を求めて
otakakot
0
410
Claude Code の Skill で複雑な既存仕様をすっきり整理しよう
yuichirokato
1
290
New in Go 1.26 Implementing go fix in product development
sunecosuri
0
330
Featured
See All Featured
Paper Plane (Part 1)
katiecoart
PRO
0
5.1k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
96
The browser strikes back
jonoalderson
0
760
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
74
Test your architecture with Archunit
thirion
1
2.2k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
130
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Abbi's Birthday
coloredviolet
2
5.1k
Ethics towards AI in product and experience design
skipperchong
2
210
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
2.8k
The Pragmatic Product Professional
lauravandoore
37
7.2k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
55k
Transcript
App Router時代のデータ 取得アーキテクチャ 2023-08-02 What's "Next" JS Meetup 基調講演 uhyo
(株式会社バベル プリンシパルエンジニア)
登壇者紹介 uhyo 2022年10月から株式会社バベル勤務。 設計やレビューを中心としつつ、 何でも屋として活動。 TypeScript入門書 好評発売中! 今年も増刷した→
会社紹介 株式会社バベル 社名のわりにJavaScriptのビルドに Babelを使っていないことで有名。 “世界中の人々の役に立つ事業を創り続ける”をミッションとする
プロダクト紹介 商談解析クラウド セールス分野をターゲットとし、営業現場の業務効率化 と「売れる」営業人材の育成を支援する。 • オンライン商談を録画し、AIが解析 • 効率的に見返しフィードバックすることができる • 議事録にもなる
復習のコーナー
Next.jsって何だっけ? Reactアプリケーション向けに、 主にルーターとサーバー実装を提供してくれる フレームワーク • ルーター: URLに応じてコンテンツを出し分ける機構 • サーバー実装: いわゆるSSRやキャッシュの機能を担当
あとバンドルの最適化まわりを頑張ってくれる
App Routerって何だっけ? Next.js 13で追加された、新しいルーターの実装。 従来のPages Routerと対比してApp Routerと 呼ばれる 特徴: •
React Server Components (RSC) の上に作られている • Pages Routerには無いさまざまな機能
レンダリング 最も単純なルーター location.href switch文的な何か ルーティング定義 DOM
レンダリング ファイルシステムベースルーティング ルーティング定義がファイルシステム上で行われるもの。 フレームワークが好んで採用する傾向にある location.href switch文的な何か ルーティング定義 ファイル システム DOM
レンダリング SSR機能 サーバー クライアント リクエストURL switch文的な何か HTML文字列 DOM バンドルされた JavaScript
ハイドレーション クライアント側ナビゲーションのときも追加のバンドルを取得したりする動きがあるが省略。 以降もナビゲーションの話は特筆すべき事情がない限り省略します レンダリング
データフェッチングって? アプリケーションの外部からデータを取得し、表示に 利用すること。 SSRしないアプリケーションであれば、普通にクライア ントからfetchしてあとは煮るなり焼くなりすれば いい。 SSRする場合は話がややこしく、フレームワークが サポートしてくれる。 ※ そもそもSSRすべきかどうかの話は別の話題なので、場外乱闘はお控えください
React 18より前の事情 サーバーサイドレンダリング用のAPI(renderToStringとか)は 同期的なレンダリングを行うAPIである。 → レンダリングの最中にデータフェッチングを行うのは不可。 → Reactアプリケーションの外部のAPIを使うことになる。 • getServerSidePropsとかそのあたり
SSR + データフェッチング サーバー クライアント リクエストURL switch文的な何か バンドルされた JavaScript データフェッチング
レンダリング HTML文字列 DOM ハイドレーション レンダリング getServerSidePropsとか
React 18の事情 Suspenseのサポートにより、SSR時も非同期的な レンダリングが可能になった(Streaming対応SSR) • SSRの最中にサスペンドしたら待ってくれて、サスペンド解消したら追 加のコンテンツを出力してくれる • レンダリングの最中にデータフェッチングを行えるように •
アーキテクチャ的には、Suspenseの導入によりステートに頼らずに ローディング中を表現できるようになったことが大きい (SSR中にステートを変化させるのは無理なので)
レンダリング Streaming SSR + データフェッチング サーバー クライアント リクエストURL switch文的な何か バンドルされた
JavaScript データフェッチング HTML文字列 DOM ハイドレーション レンダリング データフェッチング
レンダリング Streaming SSR + データフェッチング サーバー リクエストURL switch文的な何か バンドルされた JavaScript
データフェッチング HTML文字列 DOM ハイドレーション レンダリング データフェッチング Suspense対応により、データ フェッチングがレンダリングの 一部になった。
レンダリング Streaming SSR + データフェッチング サーバー リクエストURL switch文的な何か バンドルされた JavaScript
データフェッチング HTML文字列 DOM ハイドレーション レンダリング データフェッチング SSRではサーバーとクライアン トで同じものをレンダリングす るので、データフェッチングの ロジックも両側に必要になった
レンダリング Streaming SSR + データフェッチング サーバー リクエストURL switch文的な何か バンドルされた JavaScript
データフェッチング HTML文字列 DOM ハイドレーション レンダリング データフェッチング リクエストの重複排除などを考 えるとめちゃくちゃ面倒。 Streaming SSRだけに頼る のはきつい キャッシュを 渡す?
RSCがもたらした変化
RSCって何だっけ? React Server Components (RSC) では、 サーバー側コンポーネントとクライアント側コンポーネ ントという概念が導入される。 Reactアプリケーション全体で見れば、サーバー側で実 行される部分とクライアント側で実行される部分に分割
されている。 宣伝: 一言で理解するReact Server Components
レンダリング RSCのレンダリング ※ SSRしない場合の例です サーバー クライアント DOM Reactアプリケーション サーバー側 +
クライアント側 レンダリング Reactアプリケーション ただのHTML + クライアント側 バンドルされた JavaScript
レンダリング RSCのレンダリング ※ SSRしない場合の例です サーバー DOM Reactアプリケーション サーバー側 + クライアント側
レンダリング Reactアプリケーション ただのHTML + クライアント側 バンドルされた JavaScript 2ヶ所のレンダリングで、それ ぞれサーバー側コンポーネント とクライアント側コンポーネン トのレンダリングを行う。
RSC + SSR RSCはフレームワークを介して使うことが多い。フレー ムワークは普通SSRもサポートしているので、実用上は RSCとSSRを併用することが多い。 ※ いわゆるSGとかその辺りはSSRに対する最適化とみなして、 このトークでは全部まとめてSSRとして取り扱います
レンダリング (サーバー側) RSC + SSR サーバー クライアント DOM Reactアプリケーション サーバー側
+ クライアント側 Reactアプリケーション ただのHTML + クライアント側 バンドルされた JavaScript レンダリング (クライアント側) HTML文字列 レンダリング (クライアント側) ハイドレーション
レンダリング (サーバー側) RSC + SSR サーバー DOM Reactアプリケーション サーバー側 +
クライアント側 Reactアプリケーション ただのHTML + クライアント側 バンドルされた JavaScript レンダリング (クライアント側) HTML文字列 レンダリング (クライアント側) ハイドレーション ここがSSR要素 (本来クライアント側で行うレ ンダリングをサーバー側でも行 う)
RSCとデータフェッチング RSCは、サーバー側コンポーネント内で直接データ フェッチングできることを売りのひとつとしている。 • コンポーネントをasync関数にできる • →やはり状態管理無しでデータフェッチング可能
サーバー クライアント レンダリング(サーバー側) RSC + SSR DOM Reactアプリケーション サーバー側 +
クライアント側 Reactアプリケーション ただのHTML + クライアント側 バンドルされた JavaScript レンダリング (クライアント側) HTML文字列 レンダリング (クライアント側) ハイドレーション データフェッチング
RSCとデータフェッチングのポイント データフェッチングがレンダリング(サーバー側)に 含まれているため、SSRしてもサーバー側とクライアン ト側で処理が重複しない。 ハイドレーションのために面倒なことを考える必要が ない。 レンダリング(サーバー側) データフェッチング
昔のNext.jsとの比較 昔のNext.js RSC(サーバー側) リクエスト データフェッチング レンダリング HTML文字列 getServerSidePropsとか レンダリング(サーバー側) レンダリング
(クライアント側) HTML文字列 データフェッチング リクエスト
昔のNext.jsとの比較 データフェッチングに着目して比較すると、 共通点: • (クライアント側の)レンダリングより前に データフェッチングを済ませてしまうので、 ハイドレーション周りの面倒ごとが無い。 異なる点: • データフェッチングをReactアプリのレンダリングの一部
として行うか否か。
昔のNext.jsとの比較 Q. RSCでは、なぜデータフェッチングがReactアプリの 外からReactアプリの中に移動したのか?
昔のNext.jsとの比較 Q. RSCでは、なぜデータフェッチングがReactアプリの 外からReactアプリの中に移動したのか? A. データフェッチングの方法の標準化のため ※もちろん理由は1つではないが、この理由は確かDan先生がTwitter(当時)で言っていた
昔のNext.jsとの比較 昔のNext.js リクエスト データフェッチング レンダリング HTML文字列 getServerSidePropsとか レンダリング(サーバー側) レンダリング (クライアント側)
HTML文字列 データフェッチング リクエスト RSCの導入により、Next.jsの独 自概念が要らなくなった
昔のNext.jsとの比較 Q. RSCでは、なぜデータフェッチングがReactアプリの 外からReactアプリの中に移動したのか? A. データフェッチングの方法の標準化のため 昔のgetServerSideProps等はReact外の概念だったが、 新しいAPI (headers()とか)はRSCの上に作られている。 フレームワーク独自の機構が減り、フレームワーク間での共通化が進んだ。
(Reactが定める“標準”に合わせた機構となった) (RSCを受け入れないフレームワークは別)
App Router時代の データ取得アーキテクチャ
データ取得のポイント 目指すべき目標: サーバー側とクライアント側の連携をRSCに任せ、 ユーザーランドで苦労しない。 ユーザーランドの苦労の例: GraphQLクライアントのキャッシュをサーバー側からクライアント側に コピーするとか
サーバー クライアント レンダリング(サーバー側) RSC + SSR(再掲) DOM Reactアプリケーション サーバー側 +
クライアント側 Reactアプリケーション ただのHTML + クライアント側 バンドルされた JavaScript レンダリング (クライアント側) HTML文字列 レンダリング (クライアント側) ハイドレーション データフェッチング
サーバー クライアント レンダリング(サーバー側) RSC + SSR(再掲) DOM Reactアプリケーション サーバー側 +
クライアント側 Reactアプリケーション ただのHTML + クライアント側 バンドルされた JavaScript レンダリング (クライアント側) HTML文字列 レンダリング (クライアント側) ハイドレーション データフェッチング RSCによるサーバー・クライア ント連携部分
ユーザーランドで苦労しないために データ取得はサーバー側とクライアント側の2種類に 分けてけて考えよう。 • サーバー側データ取得: SSR結果(=初期レンダリング結果)に反映されてほしいもの • クライアント側データ取得: 初期レンダリングには含まれなくていいもの
サーバー クライアント レンダリング(サーバー側) DOM Reactアプリケーション サーバー側 + クライアント側 Reactアプリケーション ただのHTML
+ クライアント側 バンドルされた JavaScript レンダリング (クライアント側) HTML文字列 レンダリング (クライアント側) ハイドレーション データフェッチング サーバー側データフェッチング クライアント側データ フェッチングを発火
サーバー クライアント レンダリング(サーバー側) DOM Reactアプリケーション サーバー側 + クライアント側 Reactアプリケーション ただのHTML
+ クライアント側 バンドルされた JavaScript レンダリング (クライアント側) HTML文字列 レンダリング (クライアント側) ハイドレーション データフェッチング ポイント: ここで データフェッチング をしない
ユーザーランドで苦労しないために ポイント: Reactアプリ内でデータ取得を行えるというRSCの利点 を生かしつつSSR周りの苦労をしないために、 サーバー側で行う必要があるデータ取得は全部 Server Component内で行う。 RSCがやってくれる以外でサーバー側と クライアント側のデータ共有をしようとしない。
Server Component内の データフェッチングについて 各論1
Fetch on render でいいのか? Fetch on renderは、コンポーネントがレンダリング されたらそのコンポーネントが必要とするデータの取得 が始まることを指す。 レンダリング
→ fetch → レンダリング → 次のfetch ……という流れで通信を直列化させる問題がある。
Fetch on render でいいのか? サーバーサイドでは、fetchにかかる時間が短いことが多 い。(Next.jsサーバーとDBが同じデータセンターにあ る場合など) この場合、サーバー側コンポーネントはFetch on renderでも問題ないと考えられる。
(少なくとも、パフォーマンスボトルネックが他の場所に移る可能性は高そう)
SC内のデータフェッチング Fetch on Renderが許容されるので、上流コンポーネン トに取得をまとめるといった工夫を考える必要がない。 よって、Server Component内ではデータを必要とする コンポーネントが各々勝手にデータを取得してもよい。 ※リクエストをまとめたい別の事情があることも考えられるので、最終的には各自の事情を鑑みて判断しよう
Server Componentの テスト 各論2
データフェッチング周りのテスト BFF的なロジックをReact内で書くとなると、 それに対するユニットテストを書きたくなる。 Server Componentのテストはどうするのが良いか?
データフェッチング周りのテスト BFF的なロジックをReact内で書くとなると、 それに対するユニットテストを書きたくなる。 Server Componentのテストはどうするのが良いか? A. クライアント用コンポーネントのテストと 考え方は同じ
テストに対する考え方2案 • 普通にSCをレンダリングしてテストする。 • 今はまだできないが、そのうちできるようになる cf. https://github.com/testing-library/react-testing-library/issues/1209 • コンポーネントそのものではなく、ロジックを関数に 抜き出してテストする。
• レンダリングされるHTMLをユニットテストする必要がない場合も多 く、ロジックをフックに抜き出してテストすれば十分だったりする。 • SCではフックですらなくただのasync関数として抜き出せるので、 むしろテストしやすいかも
クライアント側の 状態管理との連携 各論3
RSCと状態管理の懸念 従来のReactでは、データフェッチングの結果は一種の 「状態」として扱われてきた。 cf. 「3種類」で管理するReactのState戦略 一方、SCでのデータフェッチング結果は、クライアント から見たら「上からpropsで降ってくる値」であり、 もはや状態ではない。
RSCと状態管理の懸念 問題: SCがフェッチした状態に関してsource of truthが React内にあるので、一部の状態管理アーキテクチャと の相性が微妙 • ReduxとかRecoil型アーキテクチャでは状態管理をReactコン ポーネントから分離しているので、Reactの中→外
という微 妙なデータの流れが必要になる。 ※Recoilでは正確にはRecoilRootの中にあるが、アーキテクチャ的な話
RSCと状態管理の懸念 答えはまだない。 RSCと相性抜群な(クライアント用)状態管理アーキテ クチャを発明したらウケるかも?
まとめ App Router時代のデータ取得のポイントは、とにかく ハイドレーション周りの苦労を減らすこと。 そのためには、サーバー側にデータ取得を寄せるのが有効。 いわゆるFetch on Renderもわりと許容できる。 クライアント側状態管理との連携どうしたものか。誰か教えて ほしい
お約束
バベルでは商談解析クラウド を一緒に開発・ 運用するエンジニアを募集しています • TypeScriptでフロント・バックエンド両方書く感じ • テックリード・EMになりたい方も歓迎! • メールやTwitter(通称)でご連絡お待ちしています •
カジュアルな面談できます 📧
[email protected]
𝕏 @uhyo_ 採用情報