Open9
AppRouter+ApolloClientのキャッチアップ
これをベースにキャッチアップする
挙動確認用のリポジトリ
getClientの挙動
- コンポーネント外部での呼び出し = 毎回新規のインスタンス
- コンポーネント内部での呼び出し = 同一のインスタンス
getClientの内部実装
- Reactのcacheでメモ化している
- cacheについて
- メモ化した関数を初回実行時に実行する
- それ以降はキャッシュされた値を使用する
- SCでのみ動作
- メモ化された関数をコンポーネント外で呼び出すとキャッシュは使用されない
- https://ja.react.dev/reference/react/cache
function makeGetClient<
AC extends Promise<ApolloClient<any>> | ApolloClient<any>,
>(makeClient: () => AC): () => AC {
function makeWrappedClient() {
return { client: makeClient() };
}
// ここでメモ化
const cachedMakeWrappedClient = cache(makeWrappedClient);
function getClient() {
if (arguments.length) {
...
}
// ここで呼び出し、getClientはコンポーネント内部で呼び出されるので、キャッシュがあればキャッシュが使われる
const wrapper = cachedMakeWrappedClient();
if (seenWrappers && seenClients) {
...
}
return wrapper.client;
}
return getClient;
}
なぜClientをラップしているか
- リクエストごとに別のインスタンスが使われている必要がある
- Clientだけを保持して
seenClients.has(wrapper.client)
をしても、同一インスタンス化は判別がつくが、同一リクエストかの判別はつかない - wrapperを作ることで、そのwrapperはリクエストごとに一意になるので、同一リクエストかどうかの判別をつけられる
- ちなみに
seenWrappers
とseenClients
はここでしか使われていないので、warningを出すためだけにある仕組みっぽい - これによってNext.jsのfetchと同じような挙動を再現してるのかな
fetchOptionsについて
- fetchOptionsにNext.jsのfetchに渡すオプションを指定できる
const {data} = await getClient().query({
query: userQuery,
context: {fetchOptions: {next: {revalidate: 5}}},
});
- fetchOptionsに渡した値はfetchに渡される
fetchOptions Any overrides of the fetch options argument to pass to the fetch call
Route Segment Config
route-segment-configは機能してない気がする-
手元で試した感じでは機能してなかった - next devでは機能しない、next startなら機能した
- なんでそもそもリクエストごとのキャッシュなのか
- セキュリティ観点かな、別リクエストで同じインスタンスだとデータ漏洩のリスクがある
- Next.jsは大丈夫なんだろうか
- Next.jsのRequest MemoizationもReactのcacheを使っているので、リクエストごとにキャッシュは無効化されるので大丈夫
- 別ページから戻ったらどうなるか、その時の挙動がfetchOptionという予測
- リクストごとにキャッシュされている
- リクエストごと = コンポーネントごと?
- -> 違う、リクエストごと、同じコンポーネントでもリクエストが違えばキャッシュは破棄される = Apolloインスタンスは破棄される
- https://ja.react.dev/reference/react/cache#caveats
- https://zenn.dev/cybozu_frontend/articles/react-cache-and-nextjs
- Next.jsのキャッシュはページを跨いだらどうなるか
- 設定次第、リクエストごとのキャッシュはリクエストごとに無効化されるので、セキュリティ的な観点は大丈夫そう
Request Memoization
- 同一リクエストで同じリクエストは重複してリクエストされない
- これはReactの機能で、GETにのみ機能する
- このコメントの情報は古そう
- Request memoization is a React feature, not a Next.js feature. It's included here to show how it interacts with the other caching mechanisms.
- Memoization only applies to the GET method in fetch requests.
- For cases where fetch is not suitable (e.g. some database clients, CMS clients, or GraphQL clients), you can use the React cache function to memoize functions.
- これはGraphQLには適用されない、なのでapollo-client-integrationsのようなものが必要
Client Componentsの場合
ApolloNextAppProvider
を使う
なぜ?
CCの初回レンダリング時はSSRされる。その際に、インスタンスをリクエストごとに分けるために、makeClient
を受け取る