getStaticProps
getStaticPropsという関数をエクスポートすると、その関数から返されたプロップを使用してビルド時にページをプリレンダリングします。
import type { InferGetStaticPropsType, GetStaticProps } from 'next'
type Repo = {
name: string
stargazers_count: number
}
export const getStaticProps = (async (context) => {
const res = await fetch('https://api.github.com/repos/vercel/next.js')
const repo = await res.json()
return { props: { repo } }
}) satisfies GetStaticProps<{
repo: Repo
}>
export default function Page({
repo,
}: InferGetStaticPropsType<typeof getStaticProps>) {
return repo.stargazers_count
}トップレベルスコープ内のモジュールをgetStaticPropsで使用するためにインポートできます。使用されるインポートはクライアント側にバンドルされません。つまり、getStaticProps内にサーバー側コードを直接記述できます。これにはデータベースからのデータ取得も含まれます。
contextパラメータ
contextパラメータは以下のキーを含むオブジェクトです。
| 名前 | 説明 |
|---|---|
params | 動的ルートを使用するページのルートパラメータを含みます。例えば、ページ名が[id].jsの場合、paramsは{ id: ... }のようになります。これは後で説明するgetStaticPathsと一緒に使用する必要があります。 |
preview | (draftModeで廃止)ページがプレビューモードにある場合previewはtrue、そうでない場合はfalseです。 |
previewData | (draftModeで廃止)setPreviewDataによって設定されたプレビューデータです。 |
draftMode | ページがドラフトモードにある場合draftModeはtrue、そうでない場合はfalseです。 |
locale | アクティブなロケール(有効な場合)を含みます。 |
locales | サポートされているすべてのロケール(有効な場合)を含みます。 |
defaultLocale | 設定されたデフォルトロケール(有効な場合)を含みます。 |
revalidateReason | 関数が呼び出された理由を示します。以下のいずれかです。"build"(ビルド時に実行)、"stale"(再検証期間が期限切れ、または開発モードで実行中)、"on-demand"(オンデマンド再検証を通じてトリガー) |
getStaticPropsの戻り値
getStaticProps関数は、props、redirect、またはnotFoundを含むオブジェクトに続いてオプションのrevalidateプロパティを返す必要があります。
props
propsオブジェクトはキーと値のペアであり、各値はページコンポーネントによって受け取られます。渡されたプロップがJSON.stringifyでシリアライズできるように、シリアライズ可能なオブジェクトである必要があります。
export async function getStaticProps(context) {
return {
props: { message: `Next.js is awesome` }, // ページコンポーネントにプロップとして渡されます
}
}revalidate
revalidateプロパティはページの再生成が発生する可能性がある秒数です(デフォルトはfalseまたは再検証なし)。
// この関数はビルド時にサーバー側で呼び出されます。
// 再検証が有効になっていて新しいリクエストが来た場合、
// サーバーレス関数で再度呼び出される可能性があります。
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json()
return {
props: {
posts,
},
// Next.jsはページを再生成しようとします。
// - リクエストが来た場合
// - 最大で10秒ごと
revalidate: 10, // 秒単位
}
}段階的静的再生成の詳細について学びます。
ISRを活用するページのキャッシュステータスは、x-nextjs-cacheレスポンスヘッダーの値を読み取ることで判定できます。可能な値は以下の通りです。
MISS- パスはキャッシュにありません(最初のアクセス時に最大で1回発生)STALE- パスはキャッシュにありますが、再検証時間を超過しているため、バックグラウンドで更新されますHIT- パスはキャッシュにあり、再検証時間を超過していません
notFound
notFoundブール値により、ページは404ステータスと404ページを返すことができます。notFound: trueの場合、以前にページが正常に生成されていても、ページは404を返します。これは、ユーザーが生成したコンテンツが作成者によって削除される場合などのユースケースをサポートするためのものです。なお、notFoundはここで説明されているのと同じrevalidate動作に従います。
export async function getStaticProps(context) {
const res = await fetch(`https://.../data`)
const data = await res.json()
if (!data) {
return {
notFound: true,
}
}
return {
props: { data }, // ページコンポーネントにプロップとして渡されます
}
}補足:
fallback: falseモードの場合、notFoundは必要ありません。getStaticPathsから返されたパスのみがプリレンダリングされるためです。
redirect
redirectオブジェクトは内部または外部リソースへのリダイレクトを可能にします。{ destination: string, permanent: boolean }の形状と一致する必要があります。
稀に、古いHTTPクライアントが適切にリダイレクトするためにカスタムステータスコードを割り当てる必要がある場合があります。このような場合、permanentプロパティの代わりにstatusCodeプロパティを使用できます。両方の使用はできません。また、next.config.jsのリダイレクトと同様にbasePath: falseを設定できます。
export async function getStaticProps(context) {
const res = await fetch(`https://...`)
const data = await res.json()
if (!data) {
return {
redirect: {
destination: '/',
permanent: false,
// statusCode: 301
},
}
}
return {
props: { data }, // ページコンポーネントにプロップとして渡されます
}
}ビルド時にリダイレクトが既知の場合、代わりにnext.config.jsに追加する必要があります。
ファイルの読み込み:process.cwd()を使用する
getStaticPropsではファイルシステムからファイルを直接読み込むことができます。
そのためには、ファイルへの完全なパスを取得する必要があります。
Next.jsがコードを別のディレクトリにコンパイルするため、__dirnameを使用することはできません。返されるパスはPages Routerとは異なります。
代わりにprocess.cwd()を使用できます。これはNext.jsが実行されているディレクトリを示します。
import { promises as fs } from 'fs'
import path from 'path'
// postsはビルド時にgetStaticProps()によって生成されます
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>
<h3>{post.filename}</h3>
<p>{post.content}</p>
</li>
))}
</ul>
)
}
// この関数はビルド時にサーバー側で呼び出されます。
// クライアント側では呼び出されないため、
// データベースクエリを直接実行することもできます。
export async function getStaticProps() {
const postsDirectory = path.join(process.cwd(), 'posts')
const filenames = await fs.readdir(postsDirectory)
const posts = filenames.map(async (filename) => {
const filePath = path.join(postsDirectory, filename)
const fileContents = await fs.readFile(filePath, 'utf8')
// 通常、内容を解析/変換します
// 例えば、ここでMarkdownをHTMLに変換できます
return {
filename,
content: fileContents,
}
})
// { props: { posts } }を返すことで、Blogコンポーネントは
// ビルド時にプロップとして`posts`を受け取ります
return {
props: {
posts: await Promise.all(posts),
},
}
}
export default Blogバージョン履歴
| バージョン | 変更 |
|---|---|
v13.4.0 | App Routerは安定版になり、簡略化されたデータ取得が可能になりました |
v12.2.0 | オンデマンド段階的静的再生成が安定版になりました。 |
v12.1.0 | オンデマンド段階的静的再生成が追加されました(ベータ)。 |
v10.0.0 | locale、locales、defaultLocale、notFoundオプションが追加されました。 |
v10.0.0 | fallback: 'blocking'戻り値オプションが追加されました。 |
v9.5.0 | 安定版段階的静的再生成 |
v9.3.0 | 導入時期:getStaticProps |