Masayan tech blog.

  1. ブログ記事一覧>
  2. NextjsのSSR時にgetServerSidePropsで動的なデータを取得する

NextjsのSSR時にgetServerSidePropsで動的なデータを取得する

公開日

環境

  • windows10
  • DockerDesktop for Win 3.5.x
  • Laravel 8.x
  • PHP 8.x
  • node 16.13.1
  • npm 8.1.2
  • TypeScript 4.5
  • React 17.0.1
  • Next.js 12.0.7
  • Recoil 0.5.2
  • VsCode
  • gitbash 2.32.0.1

動作イメージ

  • それぞれDocker上で起動しているfrontendコンテナからapi用のbackendコンテナにリクエストを送る(ホスト側からリクエストを送るわけではないので、ポートの指定に注意)
  • 各コンテナのポートマッピングは以下の通り
    • ホスト-frontend
      • 8020: 3000
    • ホスト-backend
      • 9020: 8000
  • CSRではuseEffectでhttpリクエストなどを送る際は、ホストから
  • frontendコンテナではNext.jsが動いており、getServerSideProps()を使用してApiからデータを取得する
  • Apiからのリソースの取得については、Axiosを使用する
  • backendのApiはLaravelで作成しており、Cookieベースの認証を行う想定です

設定手順

AxiosのbaseUrlを修正

ブラウザから実行するのか、フロントエンドのサーバーから実行するのかでAxiosのbaseUrlを切り替える(frontendコンテナからだと、backendというサービス名で通信が可能となるため)

設定していないと、Error: connect ECONNREFUSEDとなる

import Axios from 'axios'
const axios = Axios.create({
  // csrとssr時のリクエスト先が異なるため
  baseURL: process.browser ? 'http://localhost:9020' : 'http://backend:8000',
  headers: { 'X-Requested-With': 'XMLHttpRequest' },
  withCredentials: true
})

export default axios

Nodeサーバーからリクエストを投げる

  • 対象のPages配下のディレクトリのコンポーネントでgetServerSidePropsを作成する
  • 認証が必要なApiのルートにリクエストを投げる際は、ctx: GetServerSidePropsContextを引数で受けることにより、ブラウザからのリクエストに包含されているcookieを取得して、Apiへリクエストを投げる際に利用することが可能(これがないと401エラーになる)
  • 上記のように、認証が必要なダッシュボードとかでもcookieを取得することは可能だが、そういったページはそもそもSEOを気にしなくてもよいので、SSRするはないという...(以下SWR公式より引用)

    This approach works well for user dashboard pages, for example. Because a dashboard is a private, user-specific page, SEO is not relevant and the page doesn’t need to be pre-rendered. The data is frequently updated, which requires request-time data fetching.

  • レスポンスはコンポーネントの引数で受けて、useEffect内等でそのまま使用することが可能
import axios from 'libs/axios'
import { GetServerSideProps } from 'next'
..

type POST = typeof postData

export const getServerSideProps: GetServerSideProps = async (ctx) => {
  const cookie = ctx.req?.headers.cookie
  const res = await axios.get('/api/posts', {
    headers: {
      cookie: cookie!
    }
  })

  const posts: POST[] = res.data
  return {
    props: {
      posts: posts
    }
  }
}

const Home = ({ posts }) => {
..

以上です。上記の通り、認証が必要なルートへのリクエストをSSRで実装しようとすると少し面倒なので、基本は、CSRとしつつ、SEOに影響するページはSSRとする(もしくはSSGとする)というスタンスがベターなのではないかと思います。(そもそも公式もSSGが推奨としている...)

まとめ

いかがでしたでしょうか。本記事では、NextjsのSSR時にgetServerSidePropsで動的なデータを取得するための設定手順について紹介しています。認証が必要なルートへのリクエストをSSRで実装しようとすると少し面倒なので、基本は、CSRとしつつ、SEOに影響するページはSSRとする(もしくはSSGとする)というスタンスがベターなのではないかと思います