OpenAINext.js2023/05/04 18:00

Next.js 13.4

要点だけを先に読めるように短く再構成したセクションです。

元記事

Quick Digest

要約

要点だけを先に読めるように短く再構成したセクションです。

openaijamodel: gpt-5-mini-2025-08-07

Next.js 13.4 リリース — App Router が安定、Turbopack と Server Actions を追加

Key Points

  • App Router が安定化
  • Turbopack(β)導入
  • Server Actions(α)追加

Summary

Next.js 13.4 は App Router の安定化リリースです。React Server Components を基盤とした新しい app/ ルーターが本番採用可能になり、ネスト可能なレイアウト、コンポーネント単位での CSS 共置、Suspense を活用したストリーミングや選択的ハイドレーションが利用できます。開発者向けには高速なローカル開発サーバーの Turbopack(β)と、クライアント側 JS を増やさずにサーバーでデータ変更を行える Server Actions(α)が導入されています。

Key Points

  • アップグレードコマンド(推奨):
npm i next@latest react@latest react-dom@latest eslint-config-next@latest
  • App Router(安定):

    • 新しいファイルベースの app/ ルーターは React Server Components と Suspense を活用
    • layout のネストと合成が可能、グローバルレイアウトやデータの共置が容易
    • 既存の pages/ と段階的に共存可能(段階的導入が可能)
  • データフェッチとレンダリング:

    • デフォルトで Server Components。async/await でデータ取得を直接行える
    • Suspense による部分的なストリーミング表示とインタラクティブ性の向上
    • ページ遷移は transition として扱われ、中断可能なナビゲーションをサポート
  • DX/構成の改善:

    • コンポーネント単位で CSS を共置してインポート可能(_app.js に限定されない)
    • Next.js 固有 API の多くを廃し、React のプリミティブに寄せた設計
  • 新機能(安定度):

    • Turbopack(β): 高速で安定したローカル開発サーバー(試用推奨)
    • Server Actions(α): クライアント JS を追加せずにサーバーでデータを変更する実験的 API

Practical migration tips

  • まず app/ ディレクトリで一部ルートを作って段階的に移行する
  • サーバーサイドでデータを取得するコンポーネントは async 関数にして fetch を使う
  • クライアントで状態管理やイベントを扱うコンポーネントは先頭に "use client" を追加
  • Suspense でフォールバックを用意して、部分ストリーミングの恩恵を受ける

References

  • 主要変更: App Router の安定化、Turbopack(β)、Server Actions(α)

Full Translation

翻訳

原文の流れを保ったまま読める翻訳セクションです。

openaijamodel: gpt-5-mini-2025-08-07

Next.js 13.4 リリース

ブログに戻る
木曜日, 2023年5月4日

投稿者: Sebastian Markbåge (@sebmarkbage), Tim Neutkens (@timneutkens)

概要

Next.js 13.4 は基盤となるリリースであり、App Router の安定化を示します。主な内容は次のとおりです。

  • App Router(Stable):
    • React Server Components
    • ネストされたルートとレイアウト(簡素化)
    • データフェッチの簡素化
    • ストリーミングと Suspense
    • 組み込みの SEO サポート
  • Turbopack(Beta): ローカル開発サーバの高速化と安定性向上
  • Server Actions(Alpha): クライアント側の JavaScript を増やさずにサーバでデータを変更

Next.js 13 の最初のリリースから半年の間、私たちは将来の Next.js—App Router—の基盤構築に注力してきました。13.4 のリリースにより、本番環境で App Router を採用し始めることができます。

ターミナル

npm i next@latest react@latest react-dom@latest eslint-config-next@latest

Next.js App Router

Next.js は 2016 年に React アプリケーションのサーバレンダリングを簡単にするためにリリースされました。より動的でパーソナライズされ、グローバルなウェブを作ることが目標です。最初の発表記事では、Next.js のいくつかの設計原則を共有しました:

  • ゼロセットアップ
  • ファイルシステムを API として使う
  • JavaScript のみ。すべては関数
  • 自動サーバレンダリングとコード分割
  • データフェッチは開発者次第

Next.js は今や6年を迎え、当初の設計原則は変わっていません。採用が進む中で、これらの原則をより良く達成するためのフレームワークの基盤アップグレードに取り組んできました。次世代の Next.js を開発し、13.4 でこの次世代が安定し、採用可能になりました。本稿では App Router の設計判断と選択について説明します。

ゼロセットアップ。ファイルシステムを API として使う

ファイルシステムベースのルーティングは Next.js のコア機能です。最初の投稿では、単一の React コンポーネントからルートを作る例を示しました:

pages/about.js // Pages Router
import React from 'react';
export default () => <h1>About us</h1>;

追加設定は不要でした。pages/ にファイルを置けば Next.js のルーターが処理してくれます。このルーティングの単純さは今も気に入っています。しかしフレームワークの利用が増えるにつれ、開発者が構築したいインターフェースの種類も増えました。レイアウト定義の改善、UI をレイアウトとしてネストする機能、読み込みやエラー状態の定義の柔軟性が求められました。

既存の Next.js ルーターにこれらを後付けするのは容易ではありませんでした。フレームワークのあらゆる部分はルーターを中心に設計される必要があります。ページ遷移、データフェッチ、キャッシュ、データの変更と再検証、ストリーミング、スタイリングなどです。ルーターをストリーミングに対応させ、レイアウトのサポートを強化するために、新しいルーターを構築することにしました。Layouts RFC の初期リリースのあと、私たちが到達したのは次のような設計です。

app/layout.js // New: App Router ✨
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

app/page.js
export default function Page() {
  return <h1>Hello, Next.js!</h1>;
}

ここで重要なのは、このコードで見えるものよりも見えない基盤です。この新しいルーター(app/ ディレクトリ経由で段階的に導入可能)は、React Server Components と Suspense を基盤にした全く異なるアーキテクチャです。この基盤により、もともと React のプリミティブを拡張するために開発された Next.js 固有の API を除去できました。たとえば、グローバルな共有レイアウトをカスタマイズするためにカスタムの _app ファイルを使う必要はなくなります。

pages/_app.js // Pages Router
// This "global layout" wraps all routes. There's no way to
// compose other layout components, and you cannot fetch global
// data from this file.
export default function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

Pages Router ではレイアウトの合成ができず、データフェッチをコンポーネントに共置できませんでした。App Router ではこれがサポートされます。

app/layout.js // New: App Router ✨
// The root layout is shared for the entire application
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

app/dashboard/layout.js // Layouts can be nested and composed
export default function DashboardLayout({ children }) {
  return (
    <section>
      <h1>Dashboard</h1>
      {children}
    </section>
  );
}

Pages Router では、サーバからの初期ペイロードをカスタマイズするために _document を使っていました。

pages/_document.js // Pages Router
// This file allows you to customize the <html> and <body> tags
// for the server request, but adds framework-specific features
// rather than writing HTML elements.
import { Html, Head, Main, NextScript } from 'next/document';
export default function Document() {
  return (
    <Html>
      <Head />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}

App Router では、Next.js から <Html>, <Head>, <Body> をインポートする必要はなく、代わりに普通の React を使います。

app/layout.js // New: App Router ✨
// The root layout is shared for the entire application
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

ファイルシステムベースの新しいルーターを構築する機会は、ルーティングに関連する多くの機能要求に応える適切なタイミングでもありました。例えば:

  • これまで外部 npm パッケージ(コンポーネントライブラリなど)からのグローバルスタイルシートは _app.js からのみインポート可能でした。これは開発者体験として理想的ではありませんでした。App Router では任意のコンポーネント内で任意の CSS ファイルをインポート(および共置)できます。
  • getServerSideProps を使ってサーバサイドレンダリングに切り替えると、ページ全体がハイドレートされるまでアプリの操作がブロックされていました。App Router ではアーキテクチャを再設計し、React Suspense と深く統合したため、ページの一部を選択的にハイドレートし、UI の他のコンポーネントのインタラクティブ性をブロックしません。コンテンツはサーバから即座にストリーミングされ、ページの体感読み込み性能が向上します。

ルーターは Next.js を機能させる中核ですが、重要なのはルーター自体ではなく、データフェッチのようなフレームワークの残りの要素とどう統合するかです。

JavaScript のみ。すべては関数

Next.js と React の開発者は JavaScript/TypeScript でコードを書き、アプリコンポーネントを構成したいと考えています。元の投稿からの例:

pages/index.js
import React from 'react';
import Head from 'next/head';
export default () => (
  <div>
    <Head>
      <meta name="viewport" content="width=device-width, initial-scale=1" />
    </Head>
    <h1>Hi. I'm mobile-ready!</h1>
  </div>
);

将来のバージョンでは、React の自動インポートなどの DX 改善を加えました。このコンポーネントは再利用可能なロジックをカプセル化し、ファイルシステムルーティングと組み合わせることで、JavaScript と HTML を書くような感覚で React アプリを始められる手軽さを提供します。

たとえばデータをフェッチしたい場合、Next.js の初期は次のようでした:

pages/index.js
import React from 'react';
import 'isomorphic-fetch';
export default class extends React.Component {
  static async getInitialProps() {
    const res = await fetch('https://api.company.com/user/123');
    const data = await res.json();
    return { username: data.profile.username };
  }
}

その後、fetch をポリフィルしてサーバとクライアントの両方で Web fetch API を使えるようにする DX 改善を行いました。フレームワークが成熟するにつれて、データフェッチの新しいパターンを模索しました。getInitialProps はサーバとクライアントの両方で実行され、React コンポーネントを拡張して Promise を作り、その結果をコンポーネントの props に渡す API でした。getInitialProps は現在でも動作しますが、顧客フィードバックに基づいて次世代のデータフェッチ API(getServerSideProps と getStaticProps)へと進化しました:

pages/index.js
// Generate a static version of the route
export async function getStaticProps(context) {
  return { props: {} };
}

// Or dynamically server-render the route
export async function getServerSideProps(context) {
  return { props: {} };
}

これらの API によりコードがどこで実行されるか(クライアントかサーバか)が明確になり、Next.js アプリは自動的に静的最適化されるようになりました。さらに static export を可能にし、サーバをサポートしない環境(例: AWS S3 バケット)へのデプロイも可能にしました。

しかし、これは "ただの JavaScript" ではありませんでした。私たちは当初の設計原則により近づきたいと考えました。Next.js が作られて以来、React コアチームと密に協力し、React のプリミティブの上にフレームワーク機能を構築してきました。この協力と React コアチームの研究開発の蓄積により、Server Components を含む最新の React アーキテクチャを通じて Next.js が目標を達成する機会が生まれました。

App Router では、親しみのある async/await 構文でデータをフェッチできます。学ぶべき新しい API はありません。デフォルトで全てのコンポーネントは React Server Components であるため、データフェッチはサーバ上で安全に行われます。例えば:

app/page.js
export default async function Page() {
  const res = await fetch('https://api.example.com/...');
  // The return value is *not* serialized
  // You can use Date, Map, Set, etc.
  const data = res.json();
  return '...';
}

重要なのは「データフェッチは開発者次第」という原則が実現されていることです。データをフェッチして任意のコンポーネントを組み合わせられます。また、Server Components エコシステム内のサードパーティコンポーネント(例: Twitter embed の react-tweet)のように、サーバ上で完全に動作するよう設計されたコンポーネントも利用できます。

app/page.js
import { Tweet } from 'react-tweet';
export default async function Page() {
  return <Tweet id="790942692909916160" />;
}

ルーターが React Suspense と統合されているため、コンテンツの一部が読み込まれている間にフォールバックをより流動的に表示し、必要に応じて段階的にコンテンツを表示できます。

app/page.js
import { Suspense } from 'react';
import { PostFeed, Weather } from './components';
export default function Page() {
  return (
    <section>
      <Suspense fallback={<p>Loading feed...</p>}>
        <PostFeed />
      </Suspense>
      <Suspense fallback={<p>Loading weather...</p>}>
        <Weather />
      </Suspense>
    </section>
  );
}

さらに、ルーターはページ遷移を transition としてマークし、ルート遷移を中断可能にします。

自動サーバレンダリングとコード分割

Next.js を作った当時、開発者はまだ手作業で webpack や babel などの設定を行い、React アプリを動かしていることが一般的でした。サーバレンダリングやコード分割のような最適化を手動で行うのは難しく、Next.js や他のフレームワークはこれらのベストプラクティスを強制する抽象化レイヤーを作りました。ルートベースのコード分割により、pages/ ディレクトリ内の各ファイルは...