AsaDesign

Next.jsワークショップやってみた④見た目整える&素早く表示する

参考サイト:Stripeに登録した商品を、Next.jsで取得・表示しよう – Zenn

概要

  • Bootstrapを使って簡単に見た目を整える。
  • getStaticProps関数を使ってビルド時にデータを取得し静的ファイルを生成する。初期描画が早い。
    =SSG(静的サイト生成):△静的ファイルなのでリアルタイム性重視のコンテンツには不向き。
  • getStaticProps関数内でrevalidateを使って、一定期間ごとにキャッシュデータを更新する。
    =ISR(インクリメンタル静的再生成):一定期間を過ぎた状態で再読み込みすると、新しい静的ファイルを生成してくれる。

Bootstrapを使う

Next.jsのデフォルトページを削除して、EC仕様にします。

pages.index.tsxを編集します。

Bootstrap特有のコンポーネントContainer, Row, Colなどを使うだけで、ある程度整った画面になりました。

import { Container, Row, Col, Image, Stack, Button } from 'react-bootstrap'


export default function Home() {
...
  <Container>
    <Stack gap={3}>
      {products.map(product => {
        return (
          <Row key={product.id}>
            <Col xs={4}>
              <Image 
                src={product.images[0]}
                alt={product.name}
                style={{maxWidth: '100%'}}
              />
            </Col>
...

getStaticPropsでビルド時に商品データを取得し、初期描画を早くする(SSG)

ここまでは一般的なReactアプリでのデータ取得とほとんど同じです。

Next.jsの場合、ページのビルド時やユーザーからのリクエストの際に「サーバー側で」データを取得してReact側に渡すことができます。

ここでは、ページのビルド時にデータを取得するgetStaticPropsメソッドを利用します。

ということで、データの取得方法を変更してみます。

bofore:ページの読み込み後にAPIを呼び出しています。

import { useState, useEffect } from 'react'

export default function Home() {
  const [products, setProducts] = useState([])
  useEffect(() => {
    fetch('http://localhost:3000/api/products')
    .then(response => response.json())
    .then(data => setProducts(data))
  }, [setProducts])
  return (
  ...

after:ビルド時点でデータの取得を済ませています。

export async function getStaticProps() {
  const products = await fetch('http://localhost:3000/api/products')
  .then(response => response.json())
  return {
    props: {
      products
    },
  }
}

export default function Home({products}: any) {
  return (
  ...

動作確認

before:リロードしたとき、画面表示までに一瞬待ちます。

after:リロードしたとき、一瞬も待つことなく画面が再表示されます。

revalidateを設定して、キャッシュの自動更新を行う(ISR)

今の状態では、外部システム(Stripe)側でデータを更新しても、アプリ側のビルドを再実行しない限り、ブラウザで表示されているデータは更新されないとのことです。

※ローカル環境だとrevalidateを使わなくても画面再読み込みでデータ更新されました。「next devで起動している環境では、常にビルドを再実行します。」と記載されている通りだと思います。

「revalidate」を使って、一定時間を過ぎると再読み込みでデータ更新されるようにします。

export async function getStaticProps() {
  const products = await fetch('http://localhost:3000/api/products')
  .then(response => response.json())
  console.log(products)
  return {
    props: {
      products
    },
    revalidate: 1 * 60  // 追記
  }
}