getStaticProps
getStaticProps
という関数をエクスポートすると、関数から返されるpropsを使用して、ビルド時にページをプリレンダリングします:
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
パラメータは、以下のキーを含むオブジェクトです:
名前 | 説明 |
---|---|
params | 動的ルートを使用するページのルートパラメータを含みます。例えば、ページ名が[id].js の場合、params は{ id: ... } のようになります。これは後で説明するgetStaticPaths と一緒に使用する必要があります。 |
preview | (draftMode は非推奨)preview は、ページがプレビューモードの場合はtrue 、そうでない場合はfalse です。 |
previewData | (draftMode は非推奨)setPreviewData によって設定されたプレビューデータ。 |
draftMode | ページがドラフトモードの場合はtrue 、そうでない場合はfalse です。 |
locale | アクティブなロケールを含みます(有効な場合)。 |
locales | サポートされているすべてのロケールを含みます(有効な場合)。 |
defaultLocale | 設定されたデフォルトロケールを含みます(有効な場合)。 |
revalidateReason | 関数が呼び出された理由を提供します。以下のいずれかになります:「build」(ビルド時に実行)、「stale」(再検証期間が期限切れ、または開発モードで実行)、「on-demand」(オンデマンド再検証によってトリガーされる) |
getStaticPropsの戻り値
getStaticProps
関数は、props
、redirect
、またはnotFound
のいずれかを含むオブジェクトを返し、オプションでrevalidate
プロパティを追加する必要があります。
props
props
オブジェクトは、各値がページコンポーネントによって受け取られるキーと値のペアです。シリアライズ可能なオブジェクトである必要があり、渡されたpropsはJSON.stringify
でシリアライズできます。
export async function getStaticProps(context) {
return {
props: { message: `Next.jsは素晴らしい` }, // ページコンポーネントにpropsとして渡されます
}
}
revalidate
revalidate
プロパティは、ページの再生成が可能になるまでの秒数です(デフォルトはfalse
または再検証なし)。
// この関数はサーバーサイドでビルド時に呼び出されます。
// 再検証が有効で、新しいリクエストがある場合、
// サーバーレス関数で再度呼び出される可能性があります
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json()
return {
props: {
posts,
},
// Next.jsは以下のタイミングでページの再生成を試みます:
// - リクエストがあった時
// - 10秒に1回まで
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 }, // ページコンポーネントにpropsとして渡されます
}
}
補足:
fallback: false
モードでは、getStaticPaths
から返されたパスのみがプリレンダリングされるため、notFound
は不要です。
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 }, // ページコンポーネントにpropsとして渡されます
}
}
リダイレクトがビルド時に既知の場合は、代わりに 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')
// 通常、コンテンツを解析/変換します
// 例えば、ここでマークダウンを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 が導入されました。 |