0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

微経験エンジニアが学ぶ「本気のNextJS」 part6

Last updated at Posted at 2025-10-20

本PJではNext.js公式チュートリアルを元に実施します。
今回はchapter7の内容となります!


🚀 データを賢く取得!Next.jsの「サーバーコンポーネント」が変えるデータフェッチの新常識

Webアプリを作るとき、一番頭を悩ませるのが「どうやってデータを取ってくるか?」ですよね。

従来は、ページの表示後にuseEffectを使ってデータを取得し、useStateでローディング状態を管理する...といった複雑な手順が当たり前でした。

しかし、Next.jsのApp Routerでは、この常識がガラッと変わります。今回は、よりシンプルで、より高速なNext.jsのデータ取得戦略を見ていきましょう!

✨ Next.jsのデフォルト!「サーバーコンポーネント」という革命

Next.js (App Router) では、私たちが作るコンポーネントは デフォルトで「サーバーコンポーネント」 として動作します。これが超強力なんです。

  • 魔法①:コンポーネントがasync/awaitを喋りだす! サーバーコンポーネントは、なんとコンポーネント関数自体をasyncにできます。
// page.tsx
export default async function Page() {
  // もうuseEffectもuseStateもいらない!
  const data = await fetchSomething();

  return <div>{data.name}</div>;
}
  • 魔法②:重い処理も"秘密"も全部サーバーにお任せ! このコンポーネントはサーバー側で実行されます。つまり...
  1. 安全!: データベースの認証情報(秘密の鍵)など、ブラウザに見せたくない情報をサーバー側に隠したままデータにアクセスできます。

  2. 高速!: 重いデータ処理や計算をすべてサーバー側で終わらせ、ブラウザには完成したHTML(結果)だけを送るので、ユーザーの端末(スマホやPC)に負荷がかかりません。

これは、レストランのキッチン(サーバー)でシェフが全ての調理(データ処理)を完璧に終え、完成した料理(HTML)だけをテーブル(クライアント)に運ぶようなものです。

🚚 ウェイターはもう不要?「API vs DB直接クエリ」

サーバーコンポーネントのおかげで、データの取得方法にも変化が起きました。

  • 従来(APIレイヤー): ブラウザ(お客さん) → API(ウェイター) → データベース(厨房) 「APIを作る」という追加作業が必要でした。

  • Next.js (サーバーコンポーネント): サーバーコンポーネント(シェフ) → データベース(厨房の冷蔵庫) サーバー側で動くので、APIという中間層を挟まずに、データベースへ直接クエリを発行できます。これにより、作るファイルの数が減り、コード全体がシンプルになります。

(※もちろん、外部のサービスを使う場合や、クライアント側でデータを頻繁に更新する場合は、従来通りAPI(ルートハンドラ)を作ることも重要です。)

😱 陥りがちな罠!「リクエストウォーターフォール」にご用心

async/awaitが便利になったからといって、何も考えずに並べるとパフォーマンスの罠にハマることがあります。それがリクエストウォーターフォール(滝) です。


// page.tsx
export default async function Page() {
  // ① 収益データを取得(例: 3秒かかる)
  const revenue = await fetchRevenue();

  // ② 最新の請求書を取得(例: 2秒かかる)
  //    ↑ fetchRevenue()の完了(3秒)を待ってから開始される
  const latestInvoices = await fetchLatestInvoices();

  // ③ カード情報を取得(例: 1秒かかる)
  //    ↑ fetchLatestInvoices()の完了(3+2=5秒)を待ってから開始される
  const cardData = await fetchCardData();

  // 全体の所要時間: 3 + 2 + 1 = 合計 6秒 😭
  // ...
}

これは、おつかいを頼んだのに、1つ目のお店が終わるまで2つ目のお店に行ってくれないのと同じです。データ同士に関連性がない場合、これは非常に無駄な待ち時間になってしまいます。

✅ 解決策は「同時おつかい」!並列データフェッチ

このウォーターフォールを解決する魔法が、JavaScriptの標準機能であるPromise.all()です。

  • アイデア: 「全部のおつかい(データ取得)を同時にスタートさせよう!」

// data.ts などでデータを取得する関数側
export async function fetchCardData() {
  try {
    // 3つのリクエストを「同時に」開始する!
    const invoiceCountPromise = sql`SELECT COUNT(*) FROM invoices`;
    const customerCountPromise = sql`SELECT COUNT(*) FROM customers`;
    const invoiceStatusPromise = sql`SELECT ... FROM invoices`;

    // 3つすべての完了を待つ
    const data = await Promise.all([
      invoiceCountPromise,
      customerCountPromise,
      invoiceStatusPromise,
    ]);
    // ...
  }
}

こうすることで、バラバラに実行していたリクエストを並列(同時)に処理できます。

先ほどの例で言えば、3秒、2秒、1秒かかる処理を同時に開始すれば、全体は一番時間のかかる処理(3秒)で完了します。6秒かかっていた処理が3秒に短縮されるのです!

(ただし、Promise.all()にも「一番遅いリクエストに全員が待たされる」という弱点はありますが、逐次実行よりは遥かに高速です。)


今回はここまで! ご覧いただきありがとうございます!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?