Next.js getServerSidePropsが動作しない原因と解決方法
Next.jsを使用していて、getServerSidePropsがうまく動作しないという問題に直面した経験はありませんか?サーバーサイドレンダリング(SSR)を実装する際に非常に便利な機能ですが、いくつかの注意点があります。本記事では、getServerSidePropsが機能しない原因と具体的な解決方法を初心者向けに解説します。
そもそもgetServerSidePropsとは
getServerSidePropsはNext.jsの機能の一つで、ページがリクエストされるたびにサーバー側でデータを取得し、そのデータをページコンポーネントに渡す関数です。SEO対策が必要な場合や、常に最新のデータを表示する必要がある場合に重宝します。
getServerSidePropsが動作しない主な原因
原因1:ファイルの配置場所が間違っている
getServerSidePropsは「pages」ディレクトリ内のファイルにのみ記述できます。これはNext.jsの重要なルールです。もしも「components」ディレクトリや「utils」ディレクトリに記述した場合、この関数は実行されません。
正しい構造:
project/
├── pages/
│ ├── index.js
│ ├── posts/
│ │ └── [id].js ← getServerSidePropsはここに記述
│ └── about.js
├── components/
└── utils/
原因2:関数をエクスポートしていない
getServerSidePropsは必ず「named export」でエクスポートする必要があります。default exportでエクスポートすると、Next.jsが認識できません。
原因3:開発サーバーを再起動していない
getServerSidePropsを追加または変更した後、開発サーバーを再起動しないと変更が反映されません。
原因4:動的ルートの設定ミス
動的ルート([id].jsなど)でgetServerSidePropsを使用する場合、paramsの処理を忘れると問題が生じます。
原因5:非同期処理の誤り
getServerSideProps内でAPIを呼び出す場合、Promiseの処理が完了するまで待機する必要があります。
原因別の解決手順
解決手順1:ファイル配置の確認と修正
まず、getServerSidePropsを記述しているファイルが「pages」ディレクトリ内にあることを確認してください。別のディレクトリに配置している場合は、pagesディレクトリに移動させます。
解決手順2:エクスポート形式の確認
以下のようにnamed exportを使用してください。
// 正しい方法
export async function getServerSideProps() {
return {
props: {}
}
}
// 間違った方法(これではダメ)
export default function getServerSideProps() {
return {
props: {}
}
}
解決手順3:開発サーバーの再起動
ターミナルで以下を実行してサーバーを再起動します。
npm run dev
解決手順4:ブラウザキャッシュのクリア
ブラウザのキャッシュが原因の場合もあります。DevToolsを開き、キャッシュを無効化してリロードしてください。
実践的なコード例
基本的な使用例
// pages/posts.js
export default function Posts({ posts }) {
return (
<div>
<h1>ブログ記事一覧</h1>
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
)
}
export async function getServerSideProps() {
try {
const response = await fetch('https://api.example.com/posts')
const posts = await response.json()
return {
props: {
posts
},
revalidate: 60 // ISR: 60秒ごとに再検証
}
} catch (error) {
console.error('Error fetching posts:', error)
return {
notFound: true // 404ページを表示
}
}
}
動的ルートの例
// pages/posts/[id].js
export default function Post({ post }) {
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
)
}
export async function getServerSideProps({ params }) {
try {
// paramsからidを取得
const { id } = params
const response = await fetch(`https://api.example.com/posts/${id}`)
// ステータスコードが404の場合
if (response.status === 404) {
return {
notFound: true
}
}
const post = await response.json()
return {
props: {
post
}
}
} catch (error) {
return {
notFound: true
}
}
}
クエリパラメータの取得例
// pages/search.js
export default function Search({ results }) {
return (
<div>
<h1>検索結果</h1>
{results.length === 0 ? (
<p>結果が見つかりません</p>
) : (
<ul>
{results.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
)}
</div>
)
}
export async function getServerSideProps({ query }) {
const { keyword } = query
if (!keyword) {
return {
props: {
results: []
}
}
}
try {
const response = await fetch(
`https://api.example.com/search?q=${encodeURIComponent(keyword)}`
)
const results = await response.json()
return {
props: {
results
}
}
} catch (error) {
return {
props: {
results: []
}
}
}
}
リダイレクトの例
// pages/old-page.js
export default function OldPage() {
return <div>このページは表示されません</div>
}
export async function getServerSideProps() {
// 別のページにリダイレクト
return {
redirect: {
destination: '/new-page',
permanent: true // 301リダイレクト
}
}
}
よくある間違いと対処法
間違い1:getServerSidePropsでlocalStorageを使用
サーバーサイドで実行される関数のため、ブラウザのAPIであるlocalStorageは使用できません。
// ❌ 間違い
export async function getServerSideProps() {
const token = localStorage.getItem('token') // エラー
return {
props: {}
}
}
// ✅ 正解
export async function getServerSideProps({ req }) {
const token = req.cookies.token // クッキーから取得
return {
props: {
token
}
}
}
間違い2:propsの値が非シリアライズ不可の場合
propsに渡すデータはJSON形式でシリアライズ可能である必要があります。関数やDateオブジェクトはそのまま渡すことはできません。
// ❌ 間違い
export async function getServerSideProps() {
return {
props: {
date: new Date(),
callback: () => {} // 関数はシリアライズできない
}
}
}
// ✅ 正解
export async function getServerSideProps() {
return {
props: {
date: new Date().toISOString(), // 文字列に変換
timestamp: new Date().getTime() // 数値に変換
}
}
}
間違い3:APIの応答時間を考慮していない
外部APIの呼び出しが遅い場合、ページの読み込み時間が長くなります。タイムアウトを設定することが重要です。
// ✅ タイムアウト付きAPI呼び出し
export async function getServerSideProps() {
try {
const controller = new AbortController()
const timeoutId = setTimeout(() => controller.abort(), 5000) // 5秒でタイムアウト
const response = await fetch('https://api.example.com/data', {
signal: controller.signal
})
clearTimeout(timeoutId)
const data = await response.json()
return {
props: { data },
revalidate: 60
}
} catch (error) {
return {
props: { data: null },
revalidate: 10 // エラー時は短い間隔で再試行
}
}
}
間違い4:環境変数へのアクセスミス
クライアントサイドではNEXT_PUBLIC_プレフィックスが必要ですが、getServerSidePropsではすべての環境変数にアクセスできます。
// pages/api-test.js
export default function Page({ apiKey }) {
return <div>APIキー設定済み</div>
}
export async function getServerSideProps() {
const apiKey = process.env.SECRET_API_KEY // プレフィックスなしでアクセス可能
return {
props: {
apiKey
}
}
}
間違い5:getStaticPropsとの混在
同じページでgetServerSidePropsとgetStaticPropsの両方を定義することはできません。どちらか一方を選択する必要があります。
// ❌ エラー(両方は定義できない)
export async function getStaticProps() {
return { props: {} }
}
export async function getServerSideProps() {
return { props: {} }
}
// ✅ どちらか一方を選ぶ
export async function getServerSideProps() {
return { props: {} }
}
デバッグ方法
コンソールログを活用
getServerSideProps内でconsole.logを使用すると、ターミナルに出力されます(ブラウザの開発者ツールには表示されません)。
export async function getServerSideProps() {
console.log('getServerSideProps実行中...') // ターミナルに表示
const data = await fetchData()
console.log('取得データ:', data)
return {
props: { data }
}
}
ネットワークタブで確認
ブラウザの開発者ツールのNetworkタブを確認して、APIリクエストが実際に送信されているか確認しましょう。
パフォーマンス最適化のポイント
getServerSidePropsを使う際は、以下の点を考慮してパフォーマンスを最適化してください:
- キャッシング戦略:可能な限りISR(増分静的再生成)の使用を検討
- APIの最適化:複数のAPIコールが必要な場合は並列実行
- エラーハンドリング:APIエラー時のフォールバック処理を実装
- リクエストタイムアウト:長時間の処理は避ける
// 複数のAPIを並列実行
export async function getServerSideProps() {
try {
const [postsRes, usersRes] = await Promise.all([
fetch('https://api.example.com/posts'),
fetch('https://api.example.com/users')
])
const posts = await postsRes.json()
const users = await usersRes.json()
return {
props: {
posts,
users
},
revalidate: 300
}
} catch (error) {
return {
notFound: true
}
}
}
まとめ
Next.jsのgetServerSidePropsが動作しない問題は、以下の原因がほとんどです:
- ファイルがpagesディレクトリにない:必ずpagesディレクトリに配置
- エクスポート形式の誤り:named exportを使用
- サーバーの再起動:コード変更後は必ず再起動
- 非シリアライズ可能なデータ:propsに渡すデータはJSON形式で
- 環境の設定ミス:環境変数の参照を確認
これらのポイントを押さえれば、getServerSidePropsの問題の大半は解決できます。開発を進める際には、ターミナルのログとブラウザの開発者ツールを活用して、段階的にデバッグすることをお勧めします。
また、最近のNext.jsではgetServerSidePropsよりもApp Routerを使用した実装が推奨されています。プロジェクトの特性に応じて、最適な方法を選択してください。

