📝

基礎から始めるNext.js【17SSG & ISR 】

2022/11/13に公開

基礎から始めるNext.js【17SSG & ISR】

YouTube: https://youtu.be/z0csydqElog

https://youtu.be/z0csydqElog

今回は「ISR」を使用して、「SSG」でデータが追加されない問題を解決します。

ISR: https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration

ISRの実装は
「getStaticProps」のreturnの値に「revalidate: 10」を追加する。
「getStaticPaths」のreturnの値の「fallback: false」を
「fallback: 'blocking'」に変更する。

こちらの2つの設定で実装できます。

ISRの実装後はデータの追加後、
1度目のアクセスでISRによってビルドが実行され、
2度目のアクセスで追加されたデータが表示できるようになります。

1度目のアクセスではデータが追加されていない、
もしくは、データの変更が反映されていない古いデータが表示される点に
注意が必要です。

ビルドコマンド
npm run build

ビルドしたアプリの起動コマンド
npm run start
pages/ssg/index.tsx
import Link from 'next/link'
import Layout from '../../components/Layout'
import { Heading } from '@chakra-ui/react'
import { ListItem, UnorderedList } from '@chakra-ui/react'
import axios from 'axios'
import { GetStaticProps } from 'next'

export const getStaticProps: GetStaticProps = async () => {
  const res = await axios.get(`http://localhost:1337/api/posts`)

  return {
    props: {
      posts: res.data.data,
    },
    revalidate: 10,
  }
}

export default function SSGPage({ posts }) {
  return (
    <Layout title="Next App TopPage" content="Generated by create next app">
      <Heading as="h1" size="4xl" mb={2}>
        SSG Posts List
      </Heading>
      <UnorderedList>
        {posts &&
          posts.map((post) => (
            <ListItem key={post.id} fontSize={20} mb={1}>
              <Link href={`/ssg/${post.id}`}>{post.attributes.title}</Link>
            </ListItem>
          ))}
      </UnorderedList>
    </Layout>
  )
}
pages/ssg/[id].tsx
import Layout from '../../components/Layout'
import { Heading } from '@chakra-ui/react'
import { ListItem, UnorderedList } from '@chakra-ui/react'
import axios from 'axios'
import { GetStaticPaths, GetStaticProps } from 'next'
import { FC } from 'react'

export const getStaticPaths: GetStaticPaths = async () => {
  const res = await axios.get(`http://localhost:1337/api/posts`)
  const paths = res.data.data.map((data: Post) => {
    return { params: { id: String(data.id) } }
  })

  return {
    paths,
    fallback: 'blocking', // can also be true or 'blocking'
  }
}

export const getStaticProps: GetStaticProps = async ({ params }) => {
  try {
    const res = await axios.get(`http://localhost:1337/api/posts/${params.id}`)

    return {
      props: {
        post: res.data.data,
      },
      revalidate: 10,
    }
  } catch (err) {
    return {
      notFound: true,
    }
  }
}

interface Post {
  id: number
  attributes: {
    title: string
    content: string
    createdAt: string
  }
}

interface Props {
  post: Post
}

const SSGDetails: FC<Props> = ({ post }) => {
  return (
    <Layout title="Next App TopPage" content="Generated by create next app">
      <Heading as="h1" size="4xl" mb={2}>
        Post Title: {post && post.attributes.title}
      </Heading>
      <UnorderedList listStyleType="none">
        <ListItem fontSize={30} mb={1}>
          {post && post.attributes.content}
        </ListItem>
      </UnorderedList>
    </Layout>
  )
}

export default SSGDetails

Discussion