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 // 追記
}
}