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

GraphQLをServer Componentsで使いたい

taro
October 31, 2023

GraphQLをServer Componentsで使いたい

BARフロントえんどう #1 「フロントエンドリアーキテクト」で使用した資料です!
https://cybozu.connpass.com/event/297123/

taro

October 31, 2023
Tweet

More Decks by taro

Other Decks in Technology

Transcript

  1. GraphQLを
    Server Componentsで使いたい
    BARフロントえんどう #1
    2023.10.31
    Ohnishi Taro(@taroro_tarotaro)

    View full-size slide

  2. 自己紹介
    ● 大西太郎( @taroro_tarotaro)
    ● ベースマキナで管理画面のローコードSaaSを作ってます
    ● もうすぐエンジニア4年目に突入します🚀
    ● GraphQL歴は半年弱くらい
    ● Next.js, Apollo Client, Go, gqlgen, Tailwind CSS, etc.

    View full-size slide

  3. はじめに

    View full-size slide

  4. はじめに
    今後のリアーキテクチャでRSC(React Server Components)の考慮は必須…
    ● RSCを使うならできるだけSC(Server Components)に寄せたい
    ● SCの強みを活かしながらGraphQLを使えるか…?

    View full-size slide

  5. GraphQLとは

    View full-size slide

  6. GraphQLとは
    ● グラフ構造に従ってclientでフィールドを指定してデータ取得ができる

    View full-size slide

  7. GraphQLとは
    ● グラフ構造に従ってclientでフィールドを指定してデータ取得ができる

    View full-size slide

  8. GraphQLとは
    ● グラフ構造に従ってclientでフィールドを指定してデータ取得ができる
    ● 1リクエストでまとめて取得する
    ○ WaterFall問題への解決策の1つ
    ■ fetch→render→fetch→render …
    ● ※パフォーマンス以外にも良さはたくさんあるが省略…
    https://www.developerway.com/posts/how-to-fetch-data-in-react

    View full-size slide

  9. GraphQLのよくある使い方
    ● 1クエリ/ページが理想
    ● 各コンポーネントで必要な値(Fragment)を宣言してルートで一括取得する
    ● 取った値はpropsかcontextで渡す

    View full-size slide

  10. SCでGraphQLを使う

    View full-size slide

  11. SCでGraphQLを使う
    SC(Server Components)
    ● Async Componentでのシンプルなデータ取得
    ● DBに近い分、各Componentで取得してもWaterfallが気にならない
    ● Suspenseでのローディングとストリーミング

    View full-size slide

  12. SCでGraphQLを使う
    SC(Server Components) × GraphQL
    ● Async Componentでのシンプルなデータ取得
    ○ 取得はできる(Apolloなどの対応も進められている)
    ● DBに近い分、各Componentで取得してもWaterfallが気にならない
    ○ 1クエリ/ページなのでWaterfallにならないのは同様
    ● Suspenseでのローディングとストリーミング

    View full-size slide

  13. SCでGraphQLを使う
    SC(Server Components) × GraphQL
    ● Async Componentでのシンプルなデータ取得
    ○ 取得はできる(Apolloなどの対応も進められている)
    ● DBに近い分、各Componentで取得してもWaterfallが気にならない
    ○ 1クエリ/ページなのでWaterfallにならないのは同様
    ● Suspenseでのローディングとストリーミング
    ○ 1クエリ/ページなので全体がローディングされてしまう
    ○ 1クエリだからストリーミングは無理…?

    View full-size slide

  14. SCでGraphQLを使う
    SC(Server Components) × GraphQL
    ● Async Componentでのシンプルなデータ取得
    ○ 取得はできる(Apolloなどの対応も進められている)
    ● DBに近い分、各Componentで取得してもWaterfallが気にならない
    ○ 1クエリ/ページなのでWaterfallにならないのは同様
    ● Suspenseでのローディングとストリーミング
    ○ 1クエリ/ページなので全体がローディングされてしまう
    ○ 1クエリだからストリーミングは無理…?
    ○ defer directive

    View full-size slide

  15. defer directive
    GraphQL responseの一部を、clientで指定して遅延(defer)できる

    View full-size slide

  16. defer directive
    GraphQL responseの一部を、clientで指定して遅延(defer)できる
    →@defer × SCで組み合わせられるか試す

    View full-size slide

  17. GraphQL @defer × SC
    SCはpromiseを渡せばSuspenseでローディングできる

    View full-size slide

  18. GraphQL @defer × SC
    SCはpromiseを渡せばSuspenseでローディングできる
    →@deferで分割したチャンクのpromiseをSCに渡す

    View full-size slide

  19. GraphQL @defer × SC
    SCはpromiseを渡せばSuspenseでローディングできる
    →@deferで分割したチャンクのpromiseをSCに渡す
    1. queryが呼ばれる
    2. 各チャンクのpromiseを作る
    3. promiseを各コンポーネントに渡す
    4. 各チャンクが返ってきたらpromiseをresolveする

    View full-size slide

  20. GraphQL @defer × SC
    SCはpromiseを渡せばSuspenseでローディングできる
    →@deferで分割したチャンクのpromiseをSCに渡す
    1. queryが呼ばれる
    2. 各チャンクのpromiseを作る
    3. promiseを各コンポーネントに渡す
    4. 各チャンクが返ってきたらpromiseをresolveする

    View full-size slide

  21. GraphQL @defer × SC
    SCはpromiseを渡せばSuspenseでローディングできる
    →@deferで分割したチャンクのpromiseをSCに渡す
    1. queryが呼ばれる
    2. 各チャンクのpromiseを作る
    3. promiseを各コンポーネントに渡す
    4. 各チャンクが返ってきたらpromiseをresolveする

    View full-size slide

  22. GraphQL @defer × SC
    SCはpromiseを渡せばSuspenseでローディングできる
    →@deferで分割したチャンクのpromiseをSCに渡す
    1. queryが呼ばれる
    2. 各チャンクのpromiseを作る
    3. promiseを各コンポーネントに渡す
    4. 各チャンクが返ってきたらpromiseをresolveする

    View full-size slide

  23. GraphQL @defer × SC
    SCはpromiseを渡せばSuspenseでローディングできる
    →@deferで分割したチャンクのpromiseをSCに渡す
    1. queryが呼ばれる
    2. 各チャンクのpromiseを作る
    3. promiseを各コンポーネントに渡す
    4. 各チャンクが返ってきたらpromiseをresolveする

    View full-size slide

  24. GraphQL @defer × SC
    promiseをどうやって渡すか…?

    View full-size slide

  25. GraphQL @defer × SC
    promiseをどうやって渡すか…?
    props(Promise型のprops…?), context(SCにはない), ...

    View full-size slide

  26. GraphQL @defer × SC
    promiseをどうやって渡すか…?
    props(Promise型のprops…?), context(SCにはない), ...
    →クラスのインスタンスでpromiseをキャッシュする

    View full-size slide

  27. GraphQL @defer × SC
    promiseをどうやって渡すか…?
    props(Promise型のprops…?), context(SCにはない), ...
    →クラスのインスタンスでpromiseをキャッシュする
    ● React.cacheでリクエスト単位にできる
    https://zenn.dev/cybozu_frontend/articles/react-cache-and-nextjs

    View full-size slide

  28. 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

    View full-size slide

  29. 出来上がったもの(アプリケーションコードのみ)
    deferするかどうかは親が決めて子は知らなくて良いのも嬉しい

    View full-size slide

  30. まとめ
    ● 素朴にSCでGraphQLを使うとSuspenseでのストリーミングが活かせない
    ● defer directiveとpromiseのキャッシュでまるでComponent単位のfetchに…!

    View full-size slide

  31. まとめ
    ● 素朴にSCでGraphQLを使うとSuspenseでのストリーミングが活かせない
    ● defer directiveとpromiseのキャッシュでまるでComponent単位のfetchに…!
    すぐ使えるか…?
    ● 今回試した方法は、あくまで僕が雑に作ったサンプル
    ● @deferなしならApollo Clientで取得可能
    ● SC, @defer, Suspenseに対応したGraphQLクライアントはまだない…?
    ● @deferに対応したGraphQLサーバーも少ない…

    View full-size slide

  32. まとめ
    ● 素朴にSCでGraphQLを使うとSuspenseでのストリーミングが活かせない
    ● defer directiveとpromiseのキャッシュでまるでComponent単位のfetchに…!
    まだ難しいところはいろいろ…(ぜひ懇親会でお話ししたいです󰢧)
    ● revalidate
    ● CCでのデータ取得
    ● SSRからのhydration

    View full-size slide

  33. ありがとうございました!

    View full-size slide