Backブログに戻る

Next.js 13.2

Next.js 13.2では、App Routerの安定化に向けた大幅な改善が導入されました。SEOサポート、Route Handlers、サーバーコンポーネント向けMDX、タイプセーフリンクなどが含まれます。

Next.js 13.2には、App Router(app)の安定化に向けた主要な改善点が含まれています:

次のコマンドを実行して今日アップデート:

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

新しいMetadata APIによる組み込みSEOサポート

Next.jsは最初から検索エンジン最適化を可能にするように設計されています。

事前レンダリングされたHTMLコンテンツを提供することは、検索エンジンのインデックス作成を改善するだけでなく、アプリケーションのパフォーマンスも向上させます。Next.jsは多くのバージョンでアプリケーションのメタデータを変更するシンプルなAPI(next/head)を提供してきましたが、App Router(app)で検索エンジン最適化を行う方法を再設計・強化したいと考えました。

新しいMetadata APIでは、サーバーコンポーネントである任意のレイアウトまたはページで明示的なメタデータ設定を使用して、メタデータ(HTMLのhead要素内のmetaおよびlinkタグなど)を定義できます。

app/layout.tsx
import type { Metadata } from 'next';
 
export const metadata: Metadata = {
  title: 'ホーム',
  description: 'Next.jsへようこそ',
};

このAPIはシンプルで構成可能であり、ストリーミングサーバーレンダリングと互換性があるように設計されています。たとえば、ルートレイアウトでアプリケーション全体の共通メタデータ属性を設定し、アプリケーション内の他のルートに対してメタデータオブジェクトを構成およびマージできます。

これには静的メタデータと動的メタデータの両方のサポートが含まれます:

layout.js / page.js
// 静的メタデータ
export const metadata = {
  title: '...',
};
 
// 動的メタデータ
export async function generateMetadata({ params, searchParams }) {
  const product = await getProduct(params.id);
  return { title: product.title };
}

すべてのメタデータオプションが利用可能で、カスタムメタデータを提供する機能も含まれます。TypeScriptプラグインを使用するか、Metadata型を追加することでTypeScriptサポートもあります。

例えば、メタデータを通じてOpen Graph画像を定義できます:

app/layout.tsx
export const metadata = {
  openGraph: {
    title: 'Next.js',
    description: 'WebのためのReactフレームワーク',
    url: 'https://nextjs.org',
    siteName: 'Next.js',
    images: [
      {
        url: 'https://nextjs.org/og.png',
        width: 800,
        height: 600,
      },
    ],
    locale: 'en-US',
    type: 'website',
  },
};
 
export default function Layout({ children }) {}

Metadata APIはApp Router(app)向けに13.2で利用可能で、以前のhead.js特別ファイルを置き換えます。pagesディレクトリでは利用できません。

SEOについて詳しく学ぶか、MetadataのAPIリファレンスを参照してください。next-seoのコミュニティパッケージと初期API設計へのフィードバックに感謝します。

カスタムRoute Handlers

App Router(app)の最初のベータリリースで欠けていた部分の1つは、pages/apiディレクトリに存在するAPIルートでした。この機会に、appの新しいルーティングシステムに深く統合された、よりモダンなバージョンのAPIルートを作成したいと考えました。

Route Handlersを使用すると、WebのRequestResponse APIを使用して、特定のルートのカスタムリクエストハンドラを作成できます。

app/example/route.ts
export async function GET(request: Request) {}

Route Handlersには、EdgeとNode.jsランタイムの両方をシームレスにサポートする同型APIがあり、ストリーミングレスポンスのサポートも含まれます。Route Handlersはページやレイアウトと同じルートセグメント設定を使用するため、一般的な静的レンダリング再検証といった長らく待望されていた機能をサポートしています。

route.tsファイルは、HTTP動詞(GETHEADOPTIONSPOSTPUTDELETEPATCH)で名前が付けられた非同期関数をエクスポートできます。これらの関数はラップして抽象化し、カスタムルートロジックのヘルパー/再利用可能なロジックを作成できます。

cookiesheadersなどの他のサーバー関数は、Route Handlers内で使用できます。これにより、サーバーコンポーネントとRoute Handlers間でコードを共有できます。

app/example/route.ts
import { cookies } from 'next/headers';
 
export async function GET(request: Request) {
  const cookieStore = cookies();
  const token = cookieStore.get('token');
 
  return new Response('Hello, Next.js!', {
    status: 200,
    headers: { 'Set-Cookie': `token=${token}` },
  });
}

Route Handlersはroute.ts特別ファイルを使用してApp Router(app)向けに13.2で利用可能です。APIルートの代替として機能するため、pagesディレクトリでは利用できません。

Route Handlersについて詳しく学ぶか、APIリファレンスを参照してください。SvelteKitの先行技術とインスピレーションに感謝します。

サーバーコンポーネント向けMDX

MDXはマークダウンのスーパーセットで、マークダウンファイル内に直接JSXを記述できます。動的なインタラクティビティを追加したり、コンテンツ内にReactコンポーネントを埋め込んだりする強力な方法です。

13.2では、Reactサーバーコンポーネントと完全に連携するMDXを使用できるようになりました。つまり、ページ読み込みが高速化され、動的UIのテンプレート作成におけるReactの強力な機能を維持しながら、クライアントサイドのJavaScriptを減らせます。必要に応じてMDXコンテンツにインタラクティビティを加えることができます。

@next/mdxプラグインは、アプリケーションのルートで定義された新しい特別なファイルmdx-components.js|tsを提供するように更新され、カスタムコンポーネントを提供します:

your-project/mdx-components.js
// このファイルでは、MDXファイルで使用するカスタムReactコンポーネントを
// 提供できます。他のライブラリからのコンポーネントを含め、
// 任意のReactコンポーネントをインポートして使用できます。
function H1({ children }) {
  // ...
}
 
function H2({ children }) {
  // ...
}
 
export function useMDXComponents(components) {
  return { h1: H1, h2: H2, ...components };
}

さらに、MDXコンテンツを取得するコミュニティパッケージnext-mdx-remotecontentlayerと協力して、Reactサーバーコンポーネントのサポートを追加しました。

サーバーコンポーネントでMDXを設定する方法について詳しく学ぶか、サンプルをデプロイしてください。

Rust製MDXパーサー

サーバーコンポーネント向けMDXを有効にする一環として、MDXパーサーをRustで書き直し、パフォーマンスを向上させました。これは、大量のMDXファイルを処理する際に顕著な速度低下が見られた以前のJavaScriptベースのパーサーに比べて大きな改善です。

next.config.jsでRustパーサーの使用を選択できます。例えば、@next/mdxと一緒に:

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    appDir: true,
    mdxRs: true,
  },
};
 
const withMDX = require('@next/mdx')();
module.exports = withMDX(nextConfig);

このプロジェクトに取り組んでくれたTitus Wormerに感謝します。Next.js以外でこれを使用したい場合は、新しいパッケージmdxjs-rsをチェックしてください。

静的型付けリンク

Next.jsは現在、appディレクトリ内のリンクを静的に型付けでき、next/linkを使用する際のタイプミスやその他のエラーを防止し、ページ間を移動する際の型安全性を向上させます。

import Link from 'next/link'
 
// ✅
<Link href="/about" />
// ✅
<Link href="/blog/nextjs" />
// ✅
<Link href={`/blog/${slug}`} />
 
// ❌ hrefが有効なルートでない場合、TypeScriptエラー
<Link href="/aboot" />

この機能を使用するには、新しいApp RouterとTypeScriptが必要です。

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    appDir: true,
    typedRoutes: true,
  },
};
 
module.exports = nextConfig;

この機能は現在ベータ版で利用可能です。rewritesredirectsはまだサポートされていません。

静的型付けルートについて詳しく学ぶ

改善されたエラーオーバーレイ

エラーの可読性とデバッグ性を向上させるため、Next.jsのエラーオーバーレイに多くの改善を加えました。

13.2では、Next.jsとReactのスタックトレースが分離され、エラーの発生源を特定しやすくなりました。さらに、エラーオーバーレイにNext.jsの現在のバージョンが表示されるようになり、バージョンが最新かどうかを理解するのに役立ちます。

13.2の改善されたエラーオーバーレイ(バージョンの古さを示す)

13.2の改善されたエラーオーバーレイ(バージョンの古さを示す)

また、Reactのハイドレーションエラーのエラー出力を改善し、より読みやすくデバッグしやすくなりました。

Turbopackの改善

Next.js 13でアルファ版として発表されたTurbopackは、ローカル開発と将来の本番ビルドの両方を高速化するように設計されたインクリメンタルバンドラーです。

私たちは、Turbopackで既存のNext.js機能をサポートし、ベータ版に向けて全体的な安定性を向上させることに焦点を当ててきました。前回のリリース以降、以下を追加しました:

  • next/dynamicのサポート
  • next.config.js内のrewritesredirectsheaderspageExtensionsのサポート
  • pages内の404とエラーのサポート
  • CSSモジュールのcomposes: ... from ...のサポート
  • Fast Refreshの信頼性とエラー回復の改善
  • CSS優先順位処理の改善
  • コンパイル時評価の改善

また、最大規模の内部Next.jsアプリケーションと初期のVercel顧客でTurbopackを使用しながら、多くのバグを修正し、安定性を向上させました。

Webpackローダーによるカスタムファイル変換

Turbopackには、いくつかのwebpackローダーのサポートと互換性が追加されました。これにより、Webpackエコシステムから多くのローダーを使用して、さまざまなタイプのファイルをJavaScriptに変換できます。@mdx-js/loader@svgr/webpackbabel-loaderなどのローダーがサポートされています。Turbopackのカスタマイズについて詳しく学ぶ

例えば、experimental.turbo.loadersを使用して、各ファイル拡張子のローダーリストを設定します:

next.config.js
module.exports = {
  experimental: {
    turbo: {
      loaders: {
        '.md': [
          {
            // オプション形式
            loader: '@mdx-js/loader',
            options: {
              format: 'md',
            },
          },
        ],
        '.svg': ['@svgr/webpack'],
      },
    },
  },
};

完全な例については、ローダーを使用したTurbopackの例をチェックしてください。

Webpackスタイルの解決エイリアス

Turbopackは現在、webpackのresolve.aliasと同様に、エイリアスを介してモジュール解決を変更するように設定できます。experimental.turbo.resolveAliasで設定します:

next.config.js
module.exports = {
  experimental: {
    turbo: {
      resolveAlias: {
        underscore: 'lodash',
        mocha: { browser: 'mocha/browser-entry.js' },
      },
    },
  },
};

Next.jsキャッシュ

Next.js 13.2では、新しいNext.jsキャッシュ(ベータ)が導入され、ISRの進化版として以下を実現します:

  • コンポーネントレベルの段階的ISR
  • ネットワークリクエストなしの高速リフレッシュ
  • 静的ページへのコード変更の迅速な再デプロイ

完全に静的なページの場合、ISRは現在と同じように機能します。静的と動的を混合したより細かいデータ取得があるページの場合、Next.jsキャッシュはより細かい一時的なキャッシュを使用します。

ReactサーバーコンポーネントとNext.js App Router(app)内のコロケーションされたデータ取得の基盤により、静的または動的データを消費コンポーネントと一緒にカプセル化できるようになりました。

app/page.jsx
export default async function Page() {
  const [staticData, dynamicData, revalidatedData] = await Promise.all([
    // 手動で無効化されるまでキャッシュ
    fetch(`https://...`),
    // すべてのリクエストで再取得
    fetch(`https://...`, { cache: 'no-store' }),
    // 10秒の有効期間でキャッシュ
    fetch(`https://...`, { next: { revalidate: 10 } }),
  ]);
 
  return <div>...</div>;
}

App Routerでローカル開発する場合、next devでサーバーコンポーネントまたはデータ読み込みコードが変更されたときのFast Refreshの速度が向上し、next startでの本番環境と同じキャッシュ動作が表示されます。

Next.jsキャッシュでは、アプリがキャッシュを制御します。サードパーティAPIではありません。これは、アップストリームが値のキャッシュ期間を制御するcache-controlヘッダーとは異なります。

Vercel Cache API を使用した Next.js キャッシュ

Vercel 上の Next.js は、フレームワーク定義のインフラストラクチャを提供します。fetch を使ったコンポーネントレベルのデータ取得などのアプリケーションコードを記述するだけで、グローバルに分散されたインフラストラクチャを追加の作業なしに構築できます。

新しい Next.js キャッシュにより、コードの変更とデータの変更を独立して行えるようになりました。これにより、静的ページの再デプロイが大幅に高速化されます。これらのページの生成には既存のキャッシュを利用できるためです。

この新しい Vercel Cache API はあらゆるフレームワークで動作するように設計されていますが、Next.js キャッシュとのネイティブな統合を備えています。ISR が Next.js キャッシュへと進化した経緯 や、Vercel にデプロイした際の Next.js キャッシュの動作について詳しく学べます。

セルフホスティング時の Next.js キャッシュ

セルフホスティング時には、デフォルトで 50 MB の LRU キャッシュが使用されます。キャッシュへのすべてのエントリはデフォルトで自動的にディスクに書き込まれます。このファイルシステムキャッシュは、現在の ISR の動作 と同様に、同じキャッシュキーを持つノード間で共有できます。

Next.js キャッシュのコアをさらにカスタマイズおよび変更したい開発者は、基盤となるキャッシュキーを変更したり、キャッシュエントリの永続化方法や場所を変更したり、永続化を完全に無効にしたりできます。

その他の改善点

  • フォント: 驚異的なコミュニティ採用を受け、@next/fontnext/font として Next.js に組み込まれました。これにより、@next/font を個別にインストールする必要がなくなりました。詳細はこちら
  • フォント: コミュニティのフィードバックに基づき、next/font のデフォルト font-display プロパティが optional から font-display: swap に変更されました。
  • パフォーマンス: ビルドプロセスを最適化し、テストでは約 550MB のメモリ使用量を削減しました (PR)。
  • パフォーマンス: プロジェクト設定の複数回読み込みを回避し、テストでは平均約 400ms のビルド高速化を実現しました (PR)。
  • パフォーマンス: エラーコンポーネントを最適化し、スタイルを変更せずに HTML ペイロードを 0.4kb 削減しました (PR)。
  • パフォーマンス: エッジバンドルサイズを約 130KB(ほぼ半分)削減し、Vercel などのエッジ環境へのデプロイ時のコールドブートサイズをさらに小さくしました (PR)。
  • セキュリティ: images.contentDispositionType: "attachment" 設定を追加し、Image Optimization API に直接アクセスした際に画像を強制的にダウンロードするようにしました (PR)。

コミュニティ

Next.js は、2,500 人以上の個人開発者、Google や Meta などの業界パートナー、そして Vercel のコアチームの共同作業の成果です。週に 390 万回以上の npm ダウンロードと 10 万以上の GitHub スターを獲得しており、Next.js は Web を構築する最も人気のある方法の一つです。

GitHub DiscussionsRedditDiscord でコミュニティに参加しましょう。

このリリースは以下の方々によってもたらされました:

そして以下の方々の貢献: @timneutkens, @loettz, @okcoker, @clive-h-townsend, @shuding, @JanKaifer, @sepiropht, @hanneslund, @huozhi, @aralroca, @balazsorban44, @cristobaldominguez95, @vinaykulk621, @Brooooooklyn, @feedthejim, @samsisle, @MarDi66, @styfle, @therealrinku, @sebmarkbage, @cravend, @hu0p, @kdy1, @ijjk, @juzhiyuan, @IvanKiral, @LukeSchlangen, @wojtekolek, @samdenty, @Josehower, @bennettdams, @SCG82, @mike-plummer, @kwonoj, @David0z, @denchance, @joulev, @wbinnssmith, @alexkirsz, @UnknownMonk, @leerob, @sairajchouhan, @imranbarbhuiya, @jomeswang, @ductnn, @thomasballinger, @chibicode, @jridgewell, @sreetamdas, @Juneezee, @SukkaW, @wyattjoh, @michaeloliverx, @cattmote, @joefreeman, @valentincostam, @qrohlf, @ossan-engineer, @rishabhpoddar, @vasucp1207, @Schniz, @andrii-bodnar, @gergelyke, @abstractvector, @wherehows, @BrodaNoel, @taep96, @abe1272001, @0xadada, @nbouvrette, @teobler, @lubakravche, @molebox, @hiddenest。