Next.jsで更新したDBデータがフロントエンドに反映されなかった話 - SSG, ISRの理解
はじめに
Next.js触り始めた人、Webアプリケーション開発初心者向け
Background
2ヶ月前くらいからWebアプリの作り方を勉強し初めて、なぜかDBデータを更新してもフロントエンドに反映されずにハマったのでまとめる
結論から
どうやらNext.jsが高機能であるが故、デフォルトで最適なページをキャッシュしていることが原因だったらしい。
revalidate
オプションを使用してISRでレンダリングすることで、Webページでデータが更新された。
概要
構成
- Backend: Node.js + MongoDB
- Frontend: Next.js
状況
-
app/title/[id]/page.tsx
にDBから取得したデータを表示させている - MongoDBの3日分のデータを30日分のデータに変更
- dbを更新したはずなのにデータが更新されない。3日分のデータが表示される。
調べてわかったこと
Next.jsはキャッシュ機能を持っており、デフォルトでは静的なページをキャッシュしている。
レンダリング方法について
そもそも、レンダリング方法にはいくつか種類がある。
違いとしては主に、「いつ」「どこで」HTMLが生成されるか
- CSR (Client Side Rendering): ブラウザでWebサーバーから取得したHTML, JS, CSSを元に、ページHTMLがレンダリングされる
- SSR (Server Side Rendering): ブラウザからのリクエストごとに、WebサーバーがHTML JS, CSSを元にページHTMLをレンダリングし、ブラウザに返す
- SSG (Static Site Generator): アプリケーションのビルド時にHTMLをプリレンダリングしてページHTMLを生成し、それをブラウザに渡す
- ISR (Incremental Static Regeneration): SSGと似ていますが、一定期間ごとに静的ページの再生成をサーバー側で行う
ref.) SSR vs CSR vs ISR vs SSG
今回のケース
今回の場合、Static Site Generation(SSG)によって生成されたページがキャッシュされ、更新がかからなかったことが問題だった。Next.jsはデフォルトで、getStaticProps
を使用しない場合、ページはBuild時に静的に生成される。
解決方法
データの更新頻度が少ない場合(たとえば1日1回)に合わせてISRを実装する。
revalidate
オプションをページ内に追加することで実現可能
export const revalidate = 86400; // 24 hours, added
export default async function PageName({ params }: { params: PageNameProps) {
// ... existing code
}
ISRを使用するメリットとしては、SSGの利点である高速レスポンスとSEOに強いなどの特徴を活かしつつ、定期的な更新を行うことができるなどが挙げられる。
おまけ: その他の解決方法
- オンデマンド再検証: 特定のイベント(例:DBの更新)をトリガーにしてページを再生成する
- 動的レンダリング:
export const dynamic = 'force-dynamic'
を使用して、毎回サーバーサイドでページを生成する
まとめ
Next.jsが高機能であるが故、Next.jsのデフォルトのSSG動作により、DBの更新がフロントエンドに反映されない問題に遭遇。デフォルトで最適なページをキャッシュしていることが原因だったらしい。
revalidate
オプションを使用してISRでレンダリングすることで、Webページでデータが更新された。
フレームワークに振り回されないためにもレンダリングの違いを理解することが身に沁みた。