ゼロから学ぶ React, Next.js⑮【Learn Next.js】Chapter8
【Chapter8】 静的レンダリングと動的レンダリング
前の章では、ダッシュボードの概要ページのデータをフェッチしました。ただし、現在のセットアップの2つの制限事項について簡単に説明しました:
- データリクエストが意図しないウォーターフォールを作成している。
- ダッシュボードは静的なので、データの更新はアプリケーションに反映されない。
この章で扱うトピック
- ⚡️ 静的レンダリングとは何か、それがアプリケーションのパフォーマンスを向上させる方法
- ⚡️ 動的レンダリングとは何か、いつ使用するか
- 📦 ダッシュボードを動的にするためのさまざまなアプローチ
- 🕓 遅いデータフェッチをシミュレートして何が起こるかを確認する
静的レンダリングとは?
静的レンダリングでは、データフェッチとレンダリングはビルド時(デプロイ時)または再検証中にサーバーで行われます。その結果は、コンテンツデリバリーネットワーク(CDN)で配信およびキャッシュできます。
メモ:コンテンツデリバリーネットワーク(CDN)
CDNとは、Webサイトのコンテンツを複製・保存し、最適な経路でエンドユーザーに配信するネットワークです。簡単にいうと、「Webコンテンツの配信をスムーズに行うネットワーク」です。[1]
ユーザーがアプリケーションにアクセスするたびに、キャッシュされた結果が提供されます。静的レンダリングにはいくつかの利点があります:
- より高速なWebサイト - プリレンダリングされたコンテンツはキャッシュされ、グローバルに配信できます。これにより、世界中のユーザーがWebサイトのコンテンツにより迅速かつ確実にアクセスできるようになります。
- サーバー負荷の削減 - コンテンツがキャッシュされるため、サーバーは各ユーザーリクエストに対してコンテンツを動的に生成する必要がありません。
- SEO - プリレンダリングされたコンテンツは、ページの読み込み時にコンテンツがすでに利用可能であるため、検索エンジンのクローラーがインデックスを付けやすくなります。これにより、検索エンジンのランキングが向上する可能性があります。
静的レンダリングは、データのないUI、または静的なブログ投稿や製品ページなど、ユーザー間で共有されるデータに役立ちます。定期的に更新される個人用データを含むダッシュボードには適していない可能性があります。
静的レンダリングの反対は動的レンダリングです。
クイズの時間です!
知識をテストし、学んだことを確認しましょう。静的レンダリングがダッシュボードアプリに適さない理由は何ですか?
A. Webサイトが遅くなるから
B. サーバーの負荷が増加するから
C. アプリケーションが最新のデータ変更を反映しないから
D. コンテンツデリバリーネットワークが必要だから
解答
C. アプリケーションが最新のデータ変更を反映しないから
ダッシュボードに最新のデータ変更を表示したい場合に、静的レンダリングはこのユースケースには適していません。
動的レンダリングとは?
動的レンダリングでは、リクエスト時(ユーザーがページにアクセスしたとき)に各ユーザーに対してサーバー上でコンテンツがレンダリングされます。動的レンダリングにはいくつかの利点があります:
- リアルタイムデータ - 動的レンダリングにより、アプリケーションはリアルタイムまたは頻繁に更新されるデータを表示できます。これは、データが頻繁に変更されるアプリケーションに最適です。
- ユーザー固有のコンテンツ - ダッシュボードやユーザープロファイルなどの個人用コンテンツを提供し、ユーザーの操作に基づいてデータを更新することが容易になります。
- リクエスト時の情報 - 動的レンダリングにより、Cookieや URL 検索パラメーターなど、リクエスト時にのみ知ることができる情報にアクセスできます。
クイズの時間です!
知識をテストし、学んだことを確認しましょう。リクエスト時にのみ知ることができる情報の種類は何ですか?
A. データベーススキーマ
B. URLパス
C. CookieとURL検索パラメータ
解答
C. CookieとURL検索パラメータ
ダッシュボードを動的にする
デフォルトでは、@vercel/postgres
は独自のキャッシュセマンティクスを設定しません。これにより、フレームワークは独自の静的および動的動作を設定できます。
Server ComponentsまたはデータフェッチingfunctionsでNext.jsのAPIであるunstable_noStore
を使用して、静的レンダリングをオプトアウトできます。これを追加しましょう。
data.ts
で、next/cache
からunstable_noStore
をインポートし、データフェッチ関数の先頭で呼び出します:
// ...
+import { unstable_noStore as noStore } from 'next/cache';
export async function fetchRevenue() {
// レスポンスがキャッシュされないようにするために、ここでnoStore()を追加します。
// これは、fetch(..., {cache: 'no-store'})と同等です。
+ noStore();
// ...
}
export async function fetchLatestInvoices() {
+ noStore();
// ...
}
export async function fetchCardData() {
+ noStore();
// ...
}
export async function fetchFilteredInvoices(
query: string,
currentPage: number,
) {
+ noStore();
// ...
}
export async function fetchInvoicesPages(query: string) {
+ noStore();
// ...
}
export async function fetchFilteredCustomers(query: string) {
+ noStore();
// ...
}
export async function fetchInvoiceById(query: string) {
+ noStore();
// ...
}
遅いデータフェッチのシミュレーション
ダッシュボードを動的にすることは良い第一歩です。ただし...前の章で述べた問題がまだ1つあります。1つのデータリクエストが他のすべてのリクエストよりも遅い場合はどうなりますか?
遅いデータフェッチをシミュレートしてみましょう。data.ts
ファイルで、fetchRevenue()
内のconsole.log
とsetTimeout
のコメントを外します:
export async function fetchRevenue() {
try {
// デモ目的で応答を人為的に遅らせます。
// 本番環境ではこれを行わないでください :)
+ console.log('Fetching revenue data...');
+ await new Promise((resolve) => setTimeout(resolve, 3000));
const data = await sql<Revenue>`SELECT * FROM revenue`;
+ console.log('Data fetch completed after 3 seconds.');
return data.rows;
} catch (error) {
console.error('Database Error:', error);
throw new Error('Failed to fetch revenue data.');
}
}
次に、新しいタブでhttp://localhost:3000/dashboard/を開き、ページの読み込みに時間がかかることに注目してください。ターミナルにも次のメッセージが表示されるはずです:
Fetching revenue data...
Data fetch completed after 3 seconds.
ここでは、遅いデータフェッチをシミュレートするために、3秒の人為的な遅延を追加しました。その結果、データのフェッチ中はページ全体がブロックされるようになりました。
これは、開発者が解決しなければならない一般的な課題につながります:
動的レンダリングでは、アプリケーションは最も遅いデータフェッチと同じくらい高速です。
次の章
Discussion