Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
GraphQLを Server Componentsで使いたい BARフロントえんどう #1 2023.10.31 Ohnishi Taro(@taroro_tarotaro)
Slide 2
Slide 2 text
自己紹介 ● 大西太郎( @taroro_tarotaro) ● ベースマキナで管理画面のローコードSaaSを作ってます ● もうすぐエンジニア4年目に突入します🚀 ● GraphQL歴は半年弱くらい ● Next.js, Apollo Client, Go, gqlgen, Tailwind CSS, etc.
Slide 3
Slide 3 text
はじめに
Slide 4
Slide 4 text
はじめに 今後のリアーキテクチャでRSC(React Server Components)の考慮は必須… ● RSCを使うならできるだけSC(Server Components)に寄せたい ● SCの強みを活かしながらGraphQLを使えるか…?
Slide 5
Slide 5 text
GraphQLとは
Slide 6
Slide 6 text
GraphQLとは ● グラフ構造に従ってclientでフィールドを指定してデータ取得ができる
Slide 7
Slide 7 text
GraphQLとは ● グラフ構造に従ってclientでフィールドを指定してデータ取得ができる
Slide 8
Slide 8 text
GraphQLとは ● グラフ構造に従ってclientでフィールドを指定してデータ取得ができる ● 1リクエストでまとめて取得する ○ WaterFall問題への解決策の1つ ■ fetch→render→fetch→render … ● ※パフォーマンス以外にも良さはたくさんあるが省略… https://www.developerway.com/posts/how-to-fetch-data-in-react
Slide 9
Slide 9 text
GraphQLのよくある使い方 ● 1クエリ/ページが理想 ● 各コンポーネントで必要な値(Fragment)を宣言してルートで一括取得する ● 取った値はpropsかcontextで渡す
Slide 10
Slide 10 text
SCでGraphQLを使う
Slide 11
Slide 11 text
SCでGraphQLを使う SC(Server Components) ● Async Componentでのシンプルなデータ取得 ● DBに近い分、各Componentで取得してもWaterfallが気にならない ● Suspenseでのローディングとストリーミング
Slide 12
Slide 12 text
SCでGraphQLを使う SC(Server Components) × GraphQL ● Async Componentでのシンプルなデータ取得 ○ 取得はできる(Apolloなどの対応も進められている) ● DBに近い分、各Componentで取得してもWaterfallが気にならない ○ 1クエリ/ページなのでWaterfallにならないのは同様 ● Suspenseでのローディングとストリーミング
Slide 13
Slide 13 text
SCでGraphQLを使う SC(Server Components) × GraphQL ● Async Componentでのシンプルなデータ取得 ○ 取得はできる(Apolloなどの対応も進められている) ● DBに近い分、各Componentで取得してもWaterfallが気にならない ○ 1クエリ/ページなのでWaterfallにならないのは同様 ● Suspenseでのローディングとストリーミング ○ 1クエリ/ページなので全体がローディングされてしまう ○ 1クエリだからストリーミングは無理…?
Slide 14
Slide 14 text
SCでGraphQLを使う SC(Server Components) × GraphQL ● Async Componentでのシンプルなデータ取得 ○ 取得はできる(Apolloなどの対応も進められている) ● DBに近い分、各Componentで取得してもWaterfallが気にならない ○ 1クエリ/ページなのでWaterfallにならないのは同様 ● Suspenseでのローディングとストリーミング ○ 1クエリ/ページなので全体がローディングされてしまう ○ 1クエリだからストリーミングは無理…? ○ defer directive
Slide 15
Slide 15 text
defer directive GraphQL responseの一部を、clientで指定して遅延(defer)できる
Slide 16
Slide 16 text
defer directive GraphQL responseの一部を、clientで指定して遅延(defer)できる →@defer × SCで組み合わせられるか試す
Slide 17
Slide 17 text
GraphQL @defer × SC SCはpromiseを渡せばSuspenseでローディングできる
Slide 18
Slide 18 text
GraphQL @defer × SC SCはpromiseを渡せばSuspenseでローディングできる →@deferで分割したチャンクのpromiseをSCに渡す
Slide 19
Slide 19 text
GraphQL @defer × SC SCはpromiseを渡せばSuspenseでローディングできる →@deferで分割したチャンクのpromiseをSCに渡す 1. queryが呼ばれる 2. 各チャンクのpromiseを作る 3. promiseを各コンポーネントに渡す 4. 各チャンクが返ってきたらpromiseをresolveする
Slide 20
Slide 20 text
GraphQL @defer × SC SCはpromiseを渡せばSuspenseでローディングできる →@deferで分割したチャンクのpromiseをSCに渡す 1. queryが呼ばれる 2. 各チャンクのpromiseを作る 3. promiseを各コンポーネントに渡す 4. 各チャンクが返ってきたらpromiseをresolveする
Slide 21
Slide 21 text
GraphQL @defer × SC SCはpromiseを渡せばSuspenseでローディングできる →@deferで分割したチャンクのpromiseをSCに渡す 1. queryが呼ばれる 2. 各チャンクのpromiseを作る 3. promiseを各コンポーネントに渡す 4. 各チャンクが返ってきたらpromiseをresolveする
Slide 22
Slide 22 text
GraphQL @defer × SC SCはpromiseを渡せばSuspenseでローディングできる →@deferで分割したチャンクのpromiseをSCに渡す 1. queryが呼ばれる 2. 各チャンクのpromiseを作る 3. promiseを各コンポーネントに渡す 4. 各チャンクが返ってきたらpromiseをresolveする
Slide 23
Slide 23 text
GraphQL @defer × SC SCはpromiseを渡せばSuspenseでローディングできる →@deferで分割したチャンクのpromiseをSCに渡す 1. queryが呼ばれる 2. 各チャンクのpromiseを作る 3. promiseを各コンポーネントに渡す 4. 各チャンクが返ってきたらpromiseをresolveする
Slide 24
Slide 24 text
GraphQL @defer × SC promiseをどうやって渡すか…?
Slide 25
Slide 25 text
GraphQL @defer × SC promiseをどうやって渡すか…? props(Promise型のprops…?), context(SCにはない), ...
Slide 26
Slide 26 text
GraphQL @defer × SC promiseをどうやって渡すか…? props(Promise型のprops…?), context(SCにはない), ... →クラスのインスタンスでpromiseをキャッシュする
Slide 27
Slide 27 text
GraphQL @defer × SC promiseをどうやって渡すか…? props(Promise型のprops…?), context(SCにはない), ... →クラスのインスタンスでpromiseをキャッシュする ● React.cacheでリクエスト単位にできる https://zenn.dev/cybozu_frontend/articles/react-cache-and-nextjs
Slide 28
Slide 28 text
GraphQL @defer × SC promiseをどうやって渡すか…? props(Promise型のprops…?), context(SCにはない), ... →クラスのインスタンスでpromiseをキャッシュする ● React.cacheでリクエスト単位にできる https://github.com/apollographql/apollo-client-nextjs/blob/main/package/src/rsc/registerApolloClient.tsx#L6-L11
Slide 29
Slide 29 text
出来上がったもの(アプリケーションコードのみ) deferするかどうかは親が決めて子は知らなくて良いのも嬉しい
Slide 30
Slide 30 text
No content
Slide 31
Slide 31 text
まとめ
Slide 32
Slide 32 text
まとめ ● 素朴にSCでGraphQLを使うとSuspenseでのストリーミングが活かせない ● defer directiveとpromiseのキャッシュでまるでComponent単位のfetchに…!
Slide 33
Slide 33 text
まとめ ● 素朴にSCでGraphQLを使うとSuspenseでのストリーミングが活かせない ● defer directiveとpromiseのキャッシュでまるでComponent単位のfetchに…! すぐ使えるか…? ● 今回試した方法は、あくまで僕が雑に作ったサンプル ● @deferなしならApollo Clientで取得可能 ● SC, @defer, Suspenseに対応したGraphQLクライアントはまだない…? ● @deferに対応したGraphQLサーバーも少ない…
Slide 34
Slide 34 text
まとめ ● 素朴にSCでGraphQLを使うとSuspenseでのストリーミングが活かせない ● defer directiveとpromiseのキャッシュでまるでComponent単位のfetchに…! まだ難しいところはいろいろ…(ぜひ懇親会でお話ししたいです) ● revalidate ● CCでのデータ取得 ● SSRからのhydration
Slide 35
Slide 35 text
ありがとうございました!