Backブログに戻る

Next.js 13

Next.js 13では、appディレクトリにおけるレイアウト、Reactサーバーコンポーネント、ストリーミングの導入に加え、Turbopack、改良されたImageコンポーネント、新たなFontコンポーネントが登場しました。

Next.js Confで発表した通り、Next.js 13(安定版)は制限なく動的なアプリケーションを構築する基盤を提供します:

Next.js 13とpagesディレクトリは安定版で本番環境に適しています。今すぐアップデートするには以下を実行:

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

新しいappディレクトリ(ベータ版)

本日、Next.jsのルーティングとレイアウト体験を改善し、Reactの未来に沿ったappディレクトリを導入します。これは以前コミュニティフィードバックのために公開したレイアウトRFCのフォローアップです。

appディレクトリは現在ベータ版であり、本番環境での使用はまだ推奨していません。Next.js 13をpagesディレクトリと共に使用し、改良されたnext/imagenext/linkコンポーネントなどの安定機能を利用しながら、自身のペースでappディレクトリを試すことができます。pagesディレクトリは当面の間サポートを継続します。

appディレクトリには以下が含まれます:

  • レイアウト: ルート間でUIを簡単に共有しつつ、状態を保持し高コストな再レンダリングを回避
  • サーバーコンポーネント: 最も動的なアプリケーションでもサーバーファーストをデフォルトに
  • ストリーミング: 即時のローディング状態を表示し、UI単位でレンダリングしながらストリーミング
  • データ取得のサポート: asyncサーバーコンポーネントと拡張されたfetch APIによりコンポーネントレベルでのデータ取得が可能

appディレクトリは既存のpages/ディレクトリから段階的に導入可能

レイアウト

app/ディレクトリにより、ナビゲーション間で状態を保持する複雑なインターフェースの構築、高コストな再レンダリングの回避、高度なルーティングパターンの実現が容易になります。さらに、レイアウトをネストしたり、コンポーネント、テスト、スタイルなどのアプリケーションコードをルートと同位置に配置(colocate)できます。

app/ディレクトリは既存のpages/ディレクトリから段階的に導入可能

app/内にルートを作成するには、単一のファイルpage.jsが必要です:

app/page.js
// このファイルはインデックスルート(/)にマッピングされます
export default function Page() {
  return <h1>Hello, Next.js!</h1>;
}

ファイルシステムを通じてレイアウトを定義できます。レイアウトは複数のページ間でUIを共有します。ナビゲーション時、レイアウトは状態を保持し、インタラクティブなまま再レンダリングされません。

app/blog/layout.js
export default function BlogLayout({ children }) {
  return <section>{children}</section>;
}

レイアウトとページの詳細を学ぶ または デプロイ例で試す

サーバーコンポーネント

app/ディレクトリはReactの新しいサーバーコンポーネントアーキテクチャをサポートします。サーバーコンポーネントとクライアントコンポーネントは、サーバーとクライアントそれぞれの強みを活かし、優れた開発者体験を提供する単一のプログラミングモデルで高速で高インタラクティブなアプリを構築できます。

サーバーコンポーネントにより、クライアントに送信されるJavaScriptの量を削減しながら複雑なインターフェースを構築する基盤が整い、初期ページ読み込みが更に高速化されます。

ルートが読み込まれると、Next.jsとReactのランタイムが読み込まれます。これはキャッシュ可能でサイズが予測可能です。このランタイムはアプリケーションが成長してもサイズが増加しません。さらに、ランタイムは非同期に読み込まれるため、サーバーからのHTMLがクライアント側で段階的に強化されます。

サーバーコンポーネントの詳細を学ぶ または デプロイ例で試す

ストリーミング

app/ディレクトリでは、UIのレンダリング単位をクライアントに段階的にレンダリングし、インクリメンタルにストリーミングする機能が導入されました。

サーバーコンポーネントとNext.jsのネストされたレイアウトにより、データを特に必要としないページの部分は即座にレンダリングでき、データ取得中の部分にはローディング状態を表示できます。このアプローチにより、ユーザーはページ全体が読み込まれるのを待たずに操作を開始できます。

コンポーネント、テスト、スタイルなどのアプリケーションコードをルートと同位置に配置可能

Vercelにデプロイ時、app/ディレクトリを使用するNext.js 13アプリケーションは、Node.jsとEdgeランタイムの両方でデフォルトでレスポンスをストリーミングし、パフォーマンスが向上します。

ストリーミングの詳細を学ぶ または デプロイ例で試す

データ取得

Reactの最近のPromiseサポートRFCでは、コンポーネント内でデータを取得しPromiseを処理する強力な新方法が導入されました:

app/page.js
async function getData() {
  const res = await fetch('https://api.example.com/...');
  // 戻り値はシリアライズされません
  // Date、Map、Setなどを返せます
  return res.json();
}
 
// これは非同期サーバーコンポーネントです
export default async function Page() {
  const data = await getData();
 
  return <main>{/* ... */}</main>;
}

ネイティブのfetch Web APIもReactとNext.jsで拡張されました。これはfetchリクエストを自動的に重複排除し、コンポーネントレベルでデータを取得、キャッシュ、再検証するための単一の柔軟な方法を提供します。つまり、静的サイト生成(SSG)、サーバーサイドレンダリング(SSR)、増分的静的再生成(ISR)のすべての利点が単一のAPIで利用可能になります:

// このリクエストは手動で無効化されるまでキャッシュされます
// `getStaticProps`と同様
// `force-cache`はデフォルトで省略可能
fetch(URL, { cache: 'force-cache' });
 
// このリクエストは毎回再取得されます
// `getServerSideProps`と同様
fetch(URL, { cache: 'no-store' });
 
// このリクエストは10秒間キャッシュされます
// `revalidate`オプション付きの`getStaticProps`と同様
fetch(URL, { next: { revalidate: 10 } });

appディレクトリでは、レイアウト、ページ、コンポーネント内でデータを取得でき、サーバーからのストリーミングレスポンスもサポートします。

ローディングやエラー状態の処理、レンダリング中のUIストリーミングのための人間工学的な方法を可能にしています。今後のリリースでは、データ変更の改善と簡素化も予定しています。

app/ディレクトリでは、新しい特別なファイルloading.jsを使用してSuspense境界付きの即時ローディングUIを自動生成できます

オープンソースコミュニティ、パッケージメンテナー、Reactエコシステムに貢献する他の企業と協力し、ReactとNext.jsの新時代に向けて構築できることを楽しみにしています。コンポーネント内でのデータ取得の同位置配置とクライアントへのJavaScript送信量削減は、コミュニティからの重要なフィードバックであり、app/ディレクトリに含めることを嬉しく思います。

データ取得の詳細を学ぶ または デプロイ例で試す

Turbopackの紹介(アルファ版)

Next.js 13には、Webpackの後継となるRustベースのTurbopackが含まれます。

Webpackは30億回以上ダウンロードされています。Web構築の重要な部分でしたが、JavaScriptベースのツールで可能な最大パフォーマンスの限界に達しました。

Next.js 12では、ネイティブRustパワードツールへの移行を開始しました。Babelからの移行から始め、トランスパイルが17倍高速化しました。次にTerserを置き換え、ミニファイが6倍高速化しました。今こそバンドリングにもネイティブ技術を全面的に採用する時です。

Next.js 13でTurbopackアルファ版を使用すると:

  • Webpack比700倍高速な更新
  • Vite比10倍高速な更新
  • Webpack比4倍高速なコールドスタート

TurbopackはWebpackの後継となるRustベースツールで、大規模アプリで700倍高速なHMRを実現

Turbopackは開発時に最小限のアセットのみをバンドルするため、起動時間が極めて高速です。3,000モジュールのアプリケーションでは、Turbopackは1.8秒で起動します。Viteは11.4秒Webpackは16.5秒かかります。

Turbopackはサーバーコンポーネント、TypeScript、JSX、CSSなどをすぐにサポートしています。アルファ版期間中は多くの機能がまだサポートされていません。Turbopackを使用したローカル反復処理の高速化についてのフィードバックをお待ちしています。

注: Next.jsのTurbopackは現在next devのみをサポートしています。サポート機能を確認してください。Turbopackによるnext buildのサポート追加にも取り組んでいます。

Next.js 13で今日からTurbopackアルファ版をnext dev --turboでお試しください。

next/image

Next.js 13では、強力な新しいImageコンポーネントが導入され、レイアウトシフトなしで画像を簡単に表示し、オンデマンドでファイルを最適化してパフォーマンスを向上できます。

Next.jsコミュニティ調査では、**回答者の70%**が本番環境でNext.js Imageコンポーネントを使用し、Core Web Vitalsの改善を確認したと報告しました。Next.js 13では、next/imageをさらに改良しています。

新しいImageコンポーネント:

  • クライアント側JavaScriptを削減
  • スタイルと設定がより簡単
  • アクセシビリティ向上のためaltタグが必須に
  • Webプラットフォームに準拠
  • ネイティブ遅延読み込みによりハイドレーション不要で更に高速化
app/page.js
import Image from 'next/image';
import avatar from './lee.png';
 
export default function Home() {
  // アクセシビリティ向上のため"alt"が必須に
  // オプション:画像ファイルをapp/ディレクトリ内に同位置配置可能
  return <Image alt="leeerob" src={avatar} placeholder="blur" />;
}

Imageコンポーネントの詳細を学ぶ または デプロイ例で試す

Next.js 13へのnext/imageアップグレード

旧Imageコンポーネントはnext/legacy/imageにリネームされました。既存のnext/image使用をnext/legacy/imageに自動更新するコードモードを提供しています。例えば、ルートから実行時、このコマンドは./pagesディレクトリでコードモードを実行します:

Terminal
npx @next/codemod next-image-to-legacy-image ./pages

コードモードの詳細を学ぶ

@next/font

Next.js 13ではまったく新しいフォントシステムが導入され:

  • フォントを自動最適化(カスタムフォント含む)
  • 外部ネットワークリクエストを削除しプライバシーとパフォーマンスを向上
  • 任意のフォントファイルの自動セルフホスティングを内蔵
  • CSSのsize-adjustプロパティを使用し自動でレイアウトシフトゼロを実現

この新しいフォントシステムでは、パフォーマンスとプライバシーを考慮しつつすべてのGoogle Fontsを便利に使用できます。CSSとフォントファイルはビルド時にダウンロードされ、他の静的アセットと共にセルフホストされます。ブラウザからGoogleへのリクエストは一切発生しません。

app/layout.js / pages/_app.js
import { Inter } from '@next/font/google';
 
const inter = Inter();
 
<html className={inter.className}></html>;

カスタムフォントもサポートされ、フォントファイルの自動セルフホスティング、キャッシュ、プリロードが含まれます。

app/layout.js / pages/_app.js
import localFont from '@next/font/local';
 
const myFont = localFont({ src: './my-font.woff2' });
 
<html className={myFont.className}></html>;

フォント読み込み体験のあらゆる部分をカスタマイズ可能で、優れたパフォーマンスとレイアウトシフトゼロを保証します。font-display、プリロード、フォールバックなどが含まれます。

新しいFontコンポーネントの詳細を学ぶ または デプロイ例で試す

next/linkでは<a>を子要素として手動で追加する必要がなくなりました。

これは12.2で実験的オプションとして追加され、現在デフォルトとなりました。Next.js 13では、<Link>は常に<a>をレンダリングし、基盤のタグにプロパティを転送できます。例えば:

import Link from 'next/link'
 
// Next.js 12: `<a>`をネストしないと除外される
<Link href="/about">
  <a>About</a>
</Link>
 
// Next.js 13: `<Link>`は常に`<a>`をレンダリング
<Link href="/about">
  About
</Link>

改良されたLinkコンポーネントの詳細を学ぶ または デプロイ例で試す

Next.js 13へのnext/linkアップグレード

Next.js 13へのリンクアップグレードには、コードベースを自動更新するコードモッドを用意しています。例えば、ルートディレクトリから実行すると、このコマンドは./pagesディレクトリに対してコードモッドを実行します:

ターミナル
npx @next/codemod new-link ./pages

コードモッドの詳細を学ぶか、ドキュメントを確認してください。

OG画像生成

ソーシャルカード(オープングラフ画像とも呼ばれる)は、コンテンツのクリック率を大幅に向上させることができ、実験によっては最大40%のコンバージョン向上が確認されています。

静的なソーシャルカードは時間がかかり、エラーが発生しやすく、メンテナンスも困難です。このため、ソーシャルカードは不足していたり、省略されることさえありました。これまで、パーソナライズが必要で動的に生成されるソーシャルカードの作成は困難でコストがかかっていました。

私たちは、Next.jsとシームレスに連携して動的ソーシャルカードを生成する新しいライブラリ**@vercel/og**を作成しました。

pages/api/og.jsx
import { ImageResponse } from '@vercel/og';
 
export const config = {
  runtime: 'experimental-edge',
};
 
export default function () {
  return new ImageResponse(
    (
      <div
        style={{
          display: 'flex',
          fontSize: 128,
          background: 'white',
          width: '100%',
          height: '100%',
        }}
      >
        Hello, World!
      </div>
    ),
  );
}

このアプローチは、Vercel Edge Functions、WebAssembly、HTMLとCSSを画像に変換する新しいコアライブラリを活用し、Reactコンポーネントの抽象化を利用することで、既存のソリューションよりも5倍高速です。

OG画像生成の詳細を学ぶか、デプロイ例を試す

ミドルウェアAPIの更新

Next.js 12では、Next.jsルーターの完全な柔軟性を実現するためにミドルウェアを導入しました。初期のAPI設計に関するフィードバックを受け、開発者体験を改善し、強力な新機能を追加しました。

リクエストにヘッダーを簡単に設定できるようになりました:

middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
 
export function middleware(request: NextRequest) {
  // リクエストヘッダーをクローンし、新しいヘッダー`x-version`を設定
  const requestHeaders = new Headers(request.headers);
  requestHeaders.set('x-version', '13');
 
  // NextResponse.rewriteでもリクエストヘッダーを設定可能
  const response = NextResponse.next({
    request: {
      // 新しいリクエストヘッダー
      headers: requestHeaders,
    },
  });
 
  // 新しいレスポンスヘッダー`x-version`を設定
  response.headers.set('x-version', '13');
  return response;
}

また、rewriteredirectを行わずに、ミドルウェアから直接レスポンスを返せるようになりました。

middleware.ts
import { NextRequest, NextResponse } from 'next/server';
import { isAuthenticated } from '@lib/auth';
 
// ミドルウェアを`/api/`で始まるパスに制限
export const config = {
  matcher: '/api/:function*',
};
 
export function middleware(request: NextRequest) {
  // 認証関数を呼び出してリクエストをチェック
  if (!isAuthenticated(request)) {
    // エラーメッセージを示すJSONでレスポンス
    return NextResponse.json(
      {
        success: false,
        message: '認証失敗',
      },
      {
        status: 401,
      },
    );
  }
}

ミドルウェアからのレスポンス送信には、現在next.config.js内のexperimental.allowMiddlewareResponseBody設定オプションが必要です。

破壊的変更

  • Reactの最低バージョンが17.0.2から18.2.0に引き上げられました。
  • Node.jsの最低バージョンが12.22.0から14.6.0に引き上げられました(12.xはサポート終了のため)(PR)。
  • swcMinify設定プロパティがfalseからtrueに変更されました。詳細はNext.jsコンパイラを参照してください。
  • next/imageインポートがnext/legacy/imageに、next/future/imagenext/imageに改名されました。コードモッドで安全に自動リネームできます。
  • next/linkの子要素に<a>タグが使用できなくなりました。レガシー動作を使用するにはlegacyBehaviorプロップを追加するか、<a>タグを削除してアップグレードしてください。コードモッドで自動アップグレード可能です。
  • User-Agentがボットの場合、ルートのプリフェッチが行われなくなりました。
  • next.config.jsの非推奨targetオプションが削除されました。
  • サポート対象ブラウザが変更され、Internet Explorerが除外され、モダンブラウザが対象になりました。Browserslistを使用して対象ブラウザを変更することは可能です。
    • Chrome 64+
    • Edge 79+
    • Firefox 67+
    • Opera 51+
    • Safari 12+

詳細はアップグレードガイドを参照してください。

コミュニティ

6年前、私たちはNext.jsを公開しました。開発者体験を簡素化するゼロコンフィギュレーションのReactフレームワークを構築することを目指しました。振り返ると、コミュニティの成長と共に実現できたものは驚くべきものです。この調子で進み続けましょう。

Next.jsは、2,400人以上の個人開発者、GoogleやMetaなどの業界パートナー、そしてコアチームの共同作業の成果です。週間300万以上のnpmダウンロードと94,000のGitHubスターを誇り、Next.jsはWebを構築する最も人気のある方法の1つです。

このリリースの基礎となる研究と実験を支援してくれたGoogle ChromeのAuroraチームに特に感謝します。

このリリースは以下の方々の貢献によって実現されました: @ijjk, @huozhi, @HaNdTriX, @iKethavel, @timneutkens, @shuding, @rishabhpoddar, @hanneslund, @balazsorban44, @devknoll, @anthonyshew, @TomerAberbach, @philippbosch, @styfle, @mauriciomutte, @hayitsdavid, @abdennor, @Kikobeats, @cjdunteman, @Mr-Afonso, @kdy1, @jaril, @abdallah-nour, @North15, @feedthejim, @brunocrosier, @Schniz, @sedlukha, @hashlash, @Ethan-Arrowood, @fireairforce, @migueloller, @leerob, @janicklas-ralph, @Trystanr, @atilafassina, @nramkissoon, @kasperadk, @valcosmos, @henriqueholtz, @nip10, @jesstelford, @lorensr, @AviAvinav, @SukkaW, @jaycedotbin, @saurabhburade, @notrab, @kwonoj, @sanruiz, @angeloashmore, @falsepopsky, @fmontes, @Gebov, @UltiRequiem, @p13lgst, @Simek, @mrkldshv, @thomasballinger, @kyliau, @AdarshKonchady, @endymion1818, @pedro757, @perkinsjr, @gnoff, @jridgewell, @silvioprog, @mabels, @nialexsan, @feugy, @jackromo888, @crazyurus, @EarlGeorge, @MariaSolOs, @lforst, @maximbaz, @maxam2017, @teobler, @Nutlope, @sunwoo0706, @WestonThayer, @Brooooooklyn, @Nsttt, @charlypoly, @aprendendofelipe, @sviridoff, @jackton1, @nuta, @Rpaudel379, @marcialca, @MarDi66, @ismaelrumzan, @javivelasco, @eltociear, @hiro0218。