ブログに戻る
2023年2月23日(木)
Next.js 13.2
投稿者: Casey Gowrie (@GowrieCasey), Jimmy Lai (@feedthejim), Luba Kravchenko (@lubakravche), Tim Neutkens (@timneutkens)
Next.js 13.2 には、App Router(app)の安定性に向けた大きな改善が含まれています:
- 組み込みのSEOサポート: 静的および動的なメタタグを設定する新しいMetadata API。
- Route Handlers: Web Request/Response をベースにしたカスタムリクエストハンドラ。
- Server ComponentsでのMDX: Markdown内でReactコンポーネントをサーバー側のみで使用可能に。
- Rust製MDXパーサ: 新しいRustプラグインによる高速なMarkdown解析。
- 改善されたエラーオーバーレイ: Next.jsとReactのスタックトレースを分離して可読性向上。
- 静的型付けされたリンク(Beta): next/link と TypeScript でリンク切れを防止。
- Turbopackの改善(Alpha): Webpackローダーとの互換性とサポートの向上。
- Next.js Cache(Beta): コンポーネント単位のProgressive ISRと、コード変更のより速い再デプロイ。
今日アップデートするには、次を実行してください:
npm i next@latest react@latest react-dom@latest eslint-config-next@latest
組み込みのSEOサポートと新しい Metadata API
Next.js は当初から検索エンジン最適化(SEO)を容易にする設計になっています。プリレンダリングされたHTMLを提供することで、検索エンジンのインデックス化が改善されるだけでなく、アプリのパフォーマンスも向上します。従来からの next/head によるメタデータ変更APIを提供してきましたが、App Router(app)向けにSEOの最適化の設計を再検討・強化しました。
新しい Metadata API を使うと、任意のレイアウトやページ(Server Componentであるもの)内で明示的なメタデータ設定により、metaやlinkタグを定義できます。
例: app/layout.tsx
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Home',
description: 'Welcome to Next.js',
};
このAPIは単純で合成可能、かつストリーミングサーバレンダリングと互換性を持つよう設計されています。例えばアプリ全体の共通メタデータをルートレイアウトで設定し、他のルートではメタデータオブジェクトを合成・マージすることができます。静的メタデータだけでなく動的メタデータもサポートします。
例: layout.js / page.js
// Static metadata
export const metadata = {
title: '...',
};
export async function generateMetadata({ params, searchParams }) {
const product = await getProduct(params.id);
return { title: product.title };
}
すべてのメタデータオプションが利用可能で、カスタムメタデータも提供できます。TypeScriptのサポートは TypeScript plugin を使うか Metadata 型を追加することで有効になります。
Open Graphの画像をメタデータで定義する例: app/layout.tsx
export const metadata = {
openGraph: {
title: 'Next.js',
description: 'The React Framework for the Web',
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 は 13.2 で App Router(app)に導入され、以前の head.js 特殊ファイルに置き換わります。pages ディレクトリでは利用できません。SEOの詳細や Metadata の API リファレンスを参照してください。
コミュニティパッケージ next-seo と初期API設計へのフィードバックに感謝します。
Custom Route Handlers(ルートハンドラ)
App Router(app)の最初のベータで欠けていた要素の一つが pages/api に存在する API Routes でした。これを機に、app の新しいルーティングシステムに深く統合された、よりモダンなAPIルートの実装を作成しました。
Route Handlers を用いると、Web Request と Response API を使用して、特定のルートに対するカスタムリクエストハンドラを作成できます。
例: app/example/route.ts
export async function GET(request: Request) {}
Route Handlers は Edge と Node.js の両ランタイムをシームレスにサポートする等方的なAPIを持ち、ストリーミングレスポンスにも対応します。Route Handlers は pages や layouts と同じルートセグメント構成を使うため、汎用的な Static Rendering や Revalidation のような長らく待望されていた機能をサポートします。
route.ts ファイルは HTTP 動詞名の非同期関数をエクスポートできます: GET, HEAD, OPTIONS, POST, PUT, DELETE, PATCH。これらの関数はラップしたり抽象化して、ヘルパーや再利用可能なロジックを作成できます。
cookies や headers といった他のサーバ関数は Route Handlers 内で使用でき、それらの抽象化が構築する Web API も利用可能です。これにより Server Components と 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 は 13.2 で App Router(app)に route.ts 特殊ファイルとして導入されます。pages ディレクトリでは利用できません。API Routes の置き換えです。Route Handlers の詳細や API リファレンスを参照してください。SvelteKit の先行事例とインスピレーションに感謝します。
Server Components向けMDX
MDX は Markdown の上位互換で、Markdown 内で直接 JSX を書けるようにします。コンテンツ内に React コンポーネントを埋め込み、動的なインタラクティビティを加える強力な手段です。
13.2 では、MDX を完全に React Server Components として使用できるようになりました。これによりクライアント側のJavaScriptが減りページ読み込みが高速化されつつ、テンプレート用の動的UIに対して React の機能を保持できます。必要に応じて MDX コンテンツにインタラクティビティを散りばめられます。
@next/mdx プラグインは、新たにアプリケーションルートに定義する特殊ファイル mdx-components.js|ts をサポートするよう更新され、カスタムコンポーネントを提供できます:
例: your-project/mdx-components.js
// This file allows you to provide custom React components
// to be used in MDX files. You can import and use any
// React component you want, including components from
// other libraries.
function H1({ children }) { /* ... / }
function H2({ children }) { / ... */ }
export function useMDXComponents(components) {
return { h1: H1, h2: H2, ...components };
}
さらに、コミュニティパッケージ next-mdx-remote や contentlayer と協力して、React Server Components を使った MDX コンテンツ取得のサポートを追加しました。Server Components での MDX のセットアップ方法やサンプルをデプロイする手順を参照してください。
Rust製MDXパーサ
Server Components向けMDXを有効にする一環として、MDXパーサを Rust で書き直し、パフォーマンスを改善しました。これは従来のJavaScriptベースのパーサに比べて大幅な改善で、多数のMDXファイルを処理する際の顕著な遅延を解消します。
next.config.js で Rust パーサの使用をオプトインできます。例えば @next/mdx を使う場合:
/** @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 パッケージをチェックしてください。
静的型付けされたリンク(Statically Typed Links)
Next.js は app ディレクトリ内で next/link のリンクを静的に型付けできるようになり、タイプミスやその他のエラーを防ぎ、ページ間ナビゲーション時の型安全性を改善します。
import Link from 'next/link'
// ✅ <Link href="/about" />
// ✅ <Link href="/blog/nextjs" />
// ✅ <Link href={`/blog/${slug}`} />
// ❌ TypeScript errors if href is not a valid route
<Link href="/aboot" />
この機能には新しい App Router と TypeScript の使用が必要です。
next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: { appDir: true, typedRoutes: true },
};
module.exports = nextConfig;
この機能は現在ベータです。rewrites と redirects はまだサポートされていません。statically typed routes の詳細を参照してください。
改善されたエラーオーバーレイ
エラーの可読性とデバッグしやすさを向上させるために、Next.js のエラーオーバーレイを多数改善しました。13.2 では Next.js と React のスタックトレースが分離され、エラーの発生箇所の特定が容易になっています。さらに、エラーオーバーレイに現在の Next.js バージョンが表示されるようになり、バージョンの古さ(staleness)を把握しやすくなりました。
React のハイドレーションエラーに関する出力も改善され、より読みやすくデバッグしやすくなっています。
Turbopack の改善
Turbopack は Next.js 13 と共に Alpha で発表されたインクリメンタルバンドラーで、ローカル開発と将来的な本番ビルドの両方を高速化することを目的としています。Turbopack をベータに移行するにあたり、既存の Next.js 機能のサポートと全体的な安定性向上に注力してきました。
前回リリース以降、以下を追加しました:
- next/dynamic のサポート
- next.config.js の rewrites, redirects, headers, pageExtensions のサポート
- pages の 404 とエラーのサポート
- CSS modules の composes: ... from ... のサポート
- Fast Refresh の信頼性とエラー回復の改善
- CSS 優先度の取り扱いの改善
- コンパイル時評価の改善
また多数のバグ修正と安定性改善を行い、社内の大規模 Next.js アプリケーションや初期のVercel顧客とともに dogfooding を行いました。
Webpackローダーを使ったカスタムファイル変換
Turbopack は一部の webpack ローダーとの互換性を提供するようになりました。これにより、@mdx-js/loader, @svgr/webpack, babel-loader のような Webpack エコシステムの多くのローダーを使用して、さまざまなタイプのファイルを JavaScript に変換できます。Turbopack のカスタマイズ方法を参照してください。
例えば、experimental.turbo.loaders を使って拡張子ごとにローダーのリストを設定できます:
module.exports = {
experimental: {
turbo: {
loaders: {
'.md': [
{
// Option format
loader: '@mdx-js/loader',
options: { format: 'md' },
},
],
'.svg': ['@svgr/webpack'],
},
},
},
};
ロード用の Turbopack サンプルをチェックして、完全な例を確認してください。
Webpackスタイルの Resolve Aliases
Turbopack は webpack の resolve.alias に似たモジュール解決の変更(エイリアス)を設定できるようになりました。experimental.turbo.resolveAlias を通じて構成します:
module.exports = {
experimental: {
turbo: {
resolveAlias: {
underscore: 'lodash',
mocha: { browser: 'mocha/browser-entry.js' },
},
},
},
};
Next.js Cache
Next.js 13.2 では新しい Next.js Cache(beta)が導入され、ISR の進化形として以下を可能にします:
- コンポーネントレベルの Progressive ISR
- ネットワークリクエストなしでの高速な更新
- 静的ページへのコード変更のより速い再デプロイ
完全に静的なページについては、ISRは従来通り動作します。静的と動的を混在させたより詳細なデータフェッチを行うページでは、Next.js Cache はより粒度の細かい一時的なキャッシュを使用します。React Server Components と Next.js App Router(app)におけるコロケートされたデータフェッチの基盤により、静的・動的データをそれを消費するコンポーネントと一緒にカプセル化できるようになりました。
例: app/page.jsx
export default async function Page() {
const [staticData, dynamicData, revalidatedData] = await Promise.all([
// Cached until manually invalidated
fetch(https://...),
// Refetched on every request
fetch(https://..., { cache: 'no-store' }),
// Cached with a lifetime of 10 seconds
fetch(https://..., { next: { revalidate: 10 } }),
]);
}
(ドキュメントはここまでのサンプルで切れていますが、Next.js Cache により個々のフェッチのキャッシュ制御を詳細に設定できることを意味します。)
上記の機能や改善点の詳細については、公式ドキュメントの各セクション(Metadata、Route Handlers、MDX、Turbopack、Next.js Cache など)およびAPIリファレンスを参照してください。