Next.jsとHasuraを連携してデータを画面に出すところまでやる(ためのSSR, SSG, ISRの概要理解)...1


はじめに

以下のゴールを達成するため、本日はついに、Next.jsとHasuraを連携してデータを画面に出すところまでやります。

特に今回は、Next.jsでApollo Clientを使ってSSR(SSG)する仕組みの部分を見て行くと思います。

Hasuraにあるデータやエンドポイントは既に用意

最終的なゴール

以下のような構成のアプリを作ることです。

目的

  • 仕事で使っている技術のキャッチアップと復習
  • 使う可能性がある技術の理解度向上

Apollo Clientの準備

以下の2つを連携させていきます。

  • Frontend: Next.jsとApolloClient
  • Backend: HasuraのGraphqlサーバ

具体的な方法はここからパクります。

Next.js公式の実例集ですね。

ここから必要な部分だけ抜き取っていきます。

具体的には👇ここら辺ですね。

vercel/next.js/blob/canary/examples/with-apollo/lib/apolloClient.js
function createApolloClient() {
  return new ApolloClient({
    ssrMode: typeof window === 'undefined',
    link: new HttpLink({
      uri: 'https://nextjs-graphql-with-prisma-simple.vercel.app/api', // Server URL (must be absolute)
      credentials: 'same-origin', // Additional fetch() options like `credentials` or `headers`
    }),
    cache: new InMemoryCache({
      typePolicies: {
        Query: {
          fields: {
            allPosts: concatPagination(),
          },
        },
      },
    }),
  })
}

export function initializeApollo(initialState = null) {
  const _apolloClient = apolloClient ?? createApolloClient()

  // If your page has Next.js data fetching methods that use Apollo Client, the initial state
  // gets hydrated here
  if (initialState) {
    // Get existing cache, loaded during client side data fetching
    const existingCache = _apolloClient.extract()

    // Merge the existing cache into data passed from getStaticProps/getServerSideProps
    const data = merge(initialState, existingCache, {
      // combine arrays using object equality (like in sets)
      arrayMerge: (destinationArray, sourceArray) => [
        ...sourceArray,
        ...destinationArray.filter((d) =>
          sourceArray.every((s) => !isEqual(d, s))
        ),
      ],
    })

    // Restore the cache with the merged data
    _apolloClient.cache.restore(data)
  }
  // For SSG and SSR always create a new Apollo Client
  if (typeof window === 'undefined') return _apolloClient
  // Create the Apollo Client once in the client
  if (!apolloClient) apolloClient = _apolloClient

  return _apolloClient
}

注目するポイントはまずここ

vercel/next.js/blob/canary/examples/with-apollo/lib/apolloClient.js
  // For SSG and SSR always create a new Apollo Client
  if (typeof window === 'undefined') return _apolloClient
  // Create the Apollo Client once in the client
  if (!apolloClient) apolloClient = _apolloClient

Next.jsは、SSR, SSG, ISRのようなbackendで実行される処理と、クライアントで実行される処理が混在しています。

タイトルにガッツリ「SSR, SSG, ISRの概要理解」とか書いておきながらアレですが、下記の記事が勉強になります。

そうすることで、Next.jsは、多様なアプリケーションに対応するために、HTMLを生成する方法を複数用意しています。

(上記とほぼ同じこと言ってます。)

HTMLはどこで生成して、どうやって受け取るかの話ですが、Apollo Clientで切り分けられています。

特に、まずここ

vercel/next.js/blob/canary/examples/with-apollo/lib/apolloClient.js
  // For SSG and SSR always create a new Apollo Client
  if (typeof window === 'undefined') return _apolloClient

 サーバーサイドで実行される、

  • 「ビルド時」にデータを取得するgetStaticProps
  • 「ビルド時」にデータを取得する(Dynamic Routing を作る)getStaticPaths

のところでは、Apollo Clientを使う場合は、毎回新しいApollo Clientインスタンスが作成されます。

次にここ

vercel/next.js/blob/canary/examples/with-apollo/lib/apolloClient.js
  // Create the Apollo Client once in the client
  if (!apolloClient) apolloClient = _apolloClient

クライアントで実行されるクエリの発行などは、最初に1回だけapolloClientを作れば使い回されます。

このサーバーサイドの処理と、クライアントサイドの処理の切り分けが適切にされていないと

アプリケーション実行に、SSGやISRなどの実行が思った通りに行かないことがあると思います。

だから結構大事な処理になるので覚えておきましょう!

では、次回以降で具体的な実装方法を見ていきましょう。

アウトプット100本ノック実施中