KAKUTA TECH BLOG

Blog Article

Next.js における fetch 完全入門

はじめに

Web アプリケーションを作っていると、必ずと言っていいほど登場するのが「fetch(フェッチ)」という言葉です。Next.js を学び始めた初学者の方の多くが、「fetch(フェッチ)とは何なのか」「データは取得しているのか、それとも保存しているのか」「結局どこにデータが存在しているのか」といった疑問を抱きます。

この記事では、Next.js を使った開発を前提に、fetch という仕組みを基礎から説明します。

参考にしたリンク

https://developer.mozilla.org/ja/docs/Web/API/Fetch_API

https://nextjs.org/docs/app/building-your-application/data-fetching/fetching

fetch とは何か

fetch とは、簡単に言うと「外部にあるデータを取りに行く仕組み」です。ブラウザやサーバーから、別のサーバーに対して「この情報をください」とリクエストを送り、その結果を受け取る一連の流れを指します。

これを一言で言うなら、「インターネット越しにデータを取りに行く方法」です。

Web サイトやアプリは、画面に表示する情報をすべて自分の中に持っているわけではありません。ブログ記事、ユーザー情報、商品一覧など、多くのデータは API と呼ばれる仕組みを通じて、外部から取得しています。その取得処理を担っているのが fetch です。

もし fetch という仕組みがなければ、アプリは自分の中にある静的な情報しか表示できません。動的なデータを扱えないため、実用的な Web アプリを作ることはほぼ不可能になります。

fetch は取得しているのか、保存しているのか

fetch について混乱しやすい点の一つが、「fetch はデータを保存しているのか」という疑問です。結論から言うと、fetch は基本的にデータを取得するだけで、永続的に保存する役割は持っていません。

fetch を実行すると、その瞬間に必要なデータを取りに行き、レスポンスとして受け取ります。そのデータはメモリ上に一時的に存在するだけで、ページの再読み込みやサーバーの再起動が起きれば消えてしまいます。

これを一言で言うなら、「fetch は取りに行くだけで、保管係ではない」ということです。

ただし、Next.js ではキャッシュという仕組みと組み合わさることで、結果的に「保存されているように見える」挙動になることがあります。この点が、初学者が混乱しやすいポイントです。

fetch したデータはどこに存在するのか

fetch によって取得されたデータは、取得した場所によって存在する場所が変わります。

  • ブラウザで fetch を実行した場合、そのデータはブラウザのメモリ上に存在します。
  • 一方、Next.js のサーバーコンポーネントで fetch を実行した場合は、サーバー側のメモリ上に存在します。

重要なのは、「fetch したデータは自動的にデータベースに保存されるわけではない」という点です。あくまで一時的に使うためのデータとして存在しています。

Next.js では、この fetch の結果をキャッシュすることで、次回以降のリクエストで同じデータを再利用できるようにしています。しかし、それは Next.js の機能であって、fetch 自体の役割ではありません。

fetch 処理の流れ

fetch の処理は、表面的には短いコードで書けますが、内部ではいくつかの段階を踏んでいます。

  1. まず、アプリケーションが API の URL に対してリクエストを送ります。
  2. 次に、API サーバーがそのリクエストを受け取り、必要なデータを用意します。
  3. そして、そのデータがレスポンスとして返され、アプリケーション側で利用できるようになります。

この一連の流れは、人が郵便で手紙を送るのに似ています。

宛先を書いて手紙を送り、相手が返事を書き、それを受け取るという流れです。fetch は、そのやり取りをプログラムで行うための仕組みだと考えると理解しやすくなります。

Next.js における fetch の特徴

Next.js では、通常の JavaScript の fetch が拡張されています。特に App Router では、fetch がフレームワークと深く結びついており、キャッシュや再検証の制御が可能になっています。

例えば、サーバーコンポーネント内で fetch を使うと、その結果は自動的にキャッシュされる場合があります。これにより、同じデータを何度も取りに行かずに済み、パフォーマンスが向上します。

この仕組みがあることで、開発者は「いつデータを取り直すか」を意識しながら実装できるようになります。

fetch を使う場面

fetch は、外部の API からデータを取得したいときに使います。

代表的な例:

  • ブログ記事を API から取得する場合
  • ユーザー情報を読み込む場合など

画面を表示するために必要なデータがアプリケーションの外にある場合、fetch はほぼ必須の存在になります。Next.js では、ページを表示する前に fetch を行い、必要なデータをそろえた状態で画面を描画することができます。

fetch を使わない場面

一方で、fetch を使わない方がよい場面も存在します。

例:

  • すでに手元にあるデータを表示するだけの場合
  • ビルド時に固定されたデータを使う場合

また、頻繁に更新されるデータを毎回最新で表示したい場合には、キャッシュの設定を慎重に行わないと、古いデータが表示され続ける可能性があります。このような場合は、fetch のオプションを調整するか、別の方法を検討する必要があります。

fetch の実装方法

Next.js で fetch を使う基本的な実装は非常にシンプルです。以下のように、API の URL を指定してデータを取得します。

const res = await fetch('<https://example.com/api/posts>')
const data = await res.json()

このコードでは、まず API にリクエストを送り、その結果を JSON として受け取っています。ここで重要なのは、fetch 自体は「通信」を行っているだけであり、データの形を扱いやすくする処理は別で行っているという点です。e

API のデータ取得はすべて fetch なのか

API からデータを取得する方法は、fetch だけではありません。axios などのライブラリも広く使われています。これらは fetch を内部で利用していたり、似た役割を持っていたりしますが、使い勝手や機能に違いがあります。

fetch はブラウザや Node.js に標準で備わっているため、追加のライブラリを導入せずに使えるという利点があります。一方、axios はエラーハンドリングや設定のしやすさといった点で便利な機能を提供しています。

Next.js では、フレームワークと統合されている fetch を使うことで、キャッシュや再検証といった機能を活かすことができます。そのため、特別な理由がない限り、まずは fetch を使うのが一般的です。

コード例

次のコードは、Next.js と microCMS を組み合わせたプロジェクトでよく使われるものです。

import { createClient } from 'microcms-js-sdk'
import { Category, Posts } from '@/types'

// 環境変数チェック
const serviceDomain = process.env['SERVICE_DOMAIN']
const apiKey = process.env['API_KEY']

if (!serviceDomain || !apiKey) {
  throw new Error('SERVICE_DOMAIN or API_KEY is not set')
}

export const client = createClient({
  serviceDomain,
  apiKey,
})

// 記事ページに必要なデータを取得
export async function getPostBySlug(slug: string): Promise<Posts | null> {
  try {
    const post = await client.get({
      endpoint: 'blog',
      queries: { filters: `slug[equals]${slug}` },
    })
    return post.contents[0] || null
  } catch {
    return null
  }
}

createClient が行っているのは、API にアクセスするための設定をまとめたオブジェクトを作ることだけです。serviceDomainapiKey といった情報を内部に保持し、「あとで API にアクセスできる状態」を用意しています。

これを一言で言うなら、「通信の準備をしているだけ」です。

重要なのは、この段階ではまだデータを取りに行っていないという点です。API に対してリクエストを送る処理は、別の場所で行われます。

もし createClient の時点で毎回 API 通信が発生していたとしたら、ファイルを import するだけで通信が走ってしまい、アプリケーションの挙動を制御するのが非常に難しくなります。そのような設計にはなっていません。

fetch が実行される本当のタイミング

fetch が実行されるのは、作成した client を使って API メソッドを呼び出した瞬間です。例えば、次のようなコードです。

const posts = await client.get<Posts>({
endpoint: 'posts',
})

この 1 行が実行されたタイミングで、microCMS の API に対してリクエストが送られます。内部的には fetch が使われ、ネットワーク通信が発生します。

client.get の中で fetch(または同等の HTTP 通信)が実行されています。

つまり、

  • 表では client.get
  • 裏では fetch(HTTP リクエスト)

という構造です。

この流れを理解していないと、「なぜこのページでだけ通信が走るのか」「なぜビルド時にエラーが出るのか」といった問題の原因が分からなくなります。

以下は、ページ表示時の処理の流れです。

ユーザーがページにアクセス
↓
page.tsx が実行される
↓
その中で getPostBySlug(slug) を呼ぶ
↓
client.get が実行される
↓
microCMS APIHTTP リクエスト(fetch)
↓
レスポンスを受け取る
↓
HTML を生成

まとめ

最後に、fetch に関する内容を整理します。

  • fetch は外部の API からデータを取得するための仕組みです
  • fetch 自体はデータを保存するものではありません
  • 取得したデータはメモリ上に一時的に存在します
  • Next.js では fetch とキャッシュが連携します
  • API 取得には fetch 以外の選択肢も存在します

fetch の役割と限界を正しく理解することで、Next.js におけるデータ取得の全体像が見えてきます。