Next.js

Next.jsとは?Reactとの違いとPages Routerの基本を解説

この記事でわかること

Next.jsの役割をPages Routerのコードで解説。SSG・SSR・ハイドレーションの違い、静的出力の制約、SEOや安全性を考える際の注意点を学べます。

Next.jsは、Reactで作る画面に、URLに応じたページの表示、HTMLの事前生成、データ取得、ビルドなどの仕組みを加えるフレームワークです。ReactはUIを構築するライブラリで、Next.jsはアプリケーション全体を組み立てるための機能を提供します。

この記事では、Pages Routerを前提に、SSG・SSR・ブラウザでの処理の違いを説明します。コードはTypeScriptを使用し、src/pages/があるプロジェクトで試せます。App Routerではページの配置やデータ取得のAPIが異なるため、同じコードをそのまま移すことはできません。

Next.jsでできること

Next.jsには、ファイルの配置からURLを決めるルーティング、Reactの画面の事前レンダリング、ページ間の移動、CSS Modules、TypeScriptの支援などがあります。サーバーを動かす構成では、API RoutesでHTTPリクエストを処理することもできます。

Pages Routerでは、src/pages/index.tsxがトップページ、src/pages/about.tsx/aboutに対応します。再利用する部品はsrc/components/などに置いて、ページから読み込みます。この部品用ディレクトリの名前は自由です。

次のコードをsrc/pages/about.tsxに保存すると、紹介ページとトップページへ戻るリンクを作れます。

import Link from 'next/link';

export default function AboutPage() {
  return (
    <main>
      <h1>SEの学習ノート</h1>
      <p>TypeScriptとNext.jsの実践例をまとめています。</p>
      <Link href="/">トップへ戻る</Link>
    </main>
  );
}

Linkはページ間の移動に使うNext.jsのコンポーネントです。Next.js 13以降の通常の書き方では、子要素にさらにaタグを追加する必要はありません。

HTMLの生成方式とブラウザの役割

SSGはビルド時にHTMLを用意する

SSGはStatic Site Generation、つまり静的サイト生成の略です。Next.jsでは、ビルド時にページのHTMLを作っておく方法を指します。Static Site Generatorは生成ツールを指す言葉で、生成方式そのものとは区別します。

公開記事、製品の説明、会社案内など、あらかじめ内容を取得でき、多くの利用者に同じ情報を配信するページに向いています。リクエストのたびに記事を取得する必要がなく、生成物をキャッシュしやすい点が利点です。

src/pages/build-info.tsxに、生成した日時を表示するページを作ってみます。

import type { GetStaticProps } from 'next';

type Props = {
  generatedAt: string;
};

export const getStaticProps: GetStaticProps<Props> = async () => {
  return {
    props: { generatedAt: new Date().toISOString() },
  };
};

export default function BuildInfoPage({ generatedAt }: Props) {
  return (
    <main>
      <h1>ビルド情報</h1>
      <p>生成日時: <time dateTime={generatedAt}>{generatedAt}</time></p>
    </main>
  );
}

通常のビルドでは、getStaticPropsがビルド環境で実行され、返した値を使ってHTMLが生成されます。開発サーバーでは確認のためリクエスト時に再実行されるので、本番と同じタイミングだと思わないようにします。ISRを使うサーバー構成では、公開後の再生成も可能です。

SSGでもJavaScriptによるフォーム操作やブラウザからのデータ取得はできます。ただし、HTMLに埋め込まれた記事本文を更新するには、静的出力の場合は再ビルドと再配置が必要です。大量のページや遅い外部APIはビルド時間に影響します。

SSRはリクエスト時にHTMLを生成する

SSRはServer-side Renderingの略です。Pages RouterではgetServerSidePropsを使い、リクエストに応じたデータからHTMLを作れます。ログイン状態などのリクエスト情報が必要なページや、その時点の情報を返したいページで検討します。

SSGの例とは別に、src/pages/request-info.tsxへ次のコードを保存すると、サーバーで処理した日時を表示できます。このページはNext.jsサーバーが必要で、静的出力用のoutput: 'export'とは併用できません。

import type { GetServerSideProps } from 'next';

type Props = {
  requestedAt: string;
};

export const getServerSideProps: GetServerSideProps<Props> = async ({ res }) => {
  res.setHeader('Cache-Control', 'private, no-store');
  return {
    props: { requestedAt: new Date().toISOString() },
  };
};

export default function RequestInfoPage({ requestedAt }: Props) {
  return (
    <main>
      <h1>リクエスト情報</h1>
      <p>処理日時: <time dateTime={requestedAt}>{requestedAt}</time></p>
    </main>
  );
}

SSRでは、外部APIの応答待ちやサーバー処理の時間もレスポンスに含まれます。導入すれば必ずSSGやブラウザ描画より速くなるわけではありません。取得するデータ量、キャッシュ、配信環境を含めて測定します。

ブラウザで動く処理との関係

サーバーやビルド環境が作ったHTMLを受け取った後、Reactがブラウザ上でイベント処理などを結び付けます。この処理をハイドレーションと呼びます。SSGやSSRのページでも、ボタンの操作や入力欄の更新にはブラウザ側のJavaScriptが必要です。

windowdocumentlocalStorageなどはブラウザのAPIです。ページを描画する関数の中で無条件に読み取ると、サーバー側のレンダリングでエラーになることがあります。ブラウザとの同期処理にはuseEffectを使い、SSRと最初のブラウザ描画が一致するように初期表示を設計します。

静的ファイルとして公開する場合

HTML・CSS・JavaScriptだけをWebサーバーへ置きたい場合は、next.config.jsで静的出力を有効にします。次はCommonJS形式の設定例です。

/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'export',
  trailingSlash: true,
};

module.exports = nextConfig;

この設定でnpm run buildを実行すると、out/へ配信用ファイルが出力されます。先ほどのSSRページはこの構成に含められません。Pages RouterのAPI Routes、ISR、デフォルトの画像最適化サーバーなども静的出力では利用できません。必要なら外部APIや画像配信サービスを組み合わせます。

SEOや安全性について誤解しやすい点

SSGとSSRは、初期HTMLに主要な文章を含める手段です。検索順位やAI検索への掲載を保証する機能ではありません。記事の正確さ、読みやすい見出し、ページ固有のタイトル、正しいリンク、クロールできる配信状態なども整える必要があります。

また、SSRがXSSを自動的に防ぐわけではありません。Reactは通常の文字列をエスケープしますが、外部HTMLの挿入などは別途安全な処理が必要です。SSGにも依存パッケージや外部スクリプトの管理が必要です。

getStaticPropsgetServerSidePropsの内部で秘密のAPIキーを使うことはできますが、返したpropsはブラウザへ送られます。秘密情報を返す値に含めないことが大切です。

次に読む記事と公式資料

具体的な導入はNext.jsをインストール、配置のルールはディレクトリ構成と役割、生成方式の実装はSSGの設定SSRの設定で説明しています。

Next.jsを導入する前の確認

必要な機能を言葉にする

公開するページ、利用者ごとの表示、更新頻度、公開先を先に整理します。SSRやAPIが必要かによって配信環境が変わるため、画面のコードだけで導入方法を決めないようにします。

サンプルの前提を揃える

この記事はPages Routerを中心に説明しています。App Routerのapp/page.tsxを使うプロジェクトで試す場合は、データ取得やメタデータの書き方も対応する資料へ切り替えてください。

Next.jsとは・ルーターの違い・学習順を確認する

y.
WRITTEN BY

y_ymo10

SEの部屋で、JavaScript・TypeScript・React.js・Next.jsの開発ノートを公開しています。

ほかの開発ノートを読む →