ブログに戻る
Thursday, April 6th 2023
Posted by Delba de Oliveira @ delba_oliveira, Tim Neutkens @ timneutkens
Next.js 13.3
Next.js 13.3 ではコミュニティから要望の多かった以下の機能が追加されました。
- File-Based Metadata API:sitemap、robots、favicon などを動的に生成できます。
- Dynamic Open Graph Images:JSX / HTML / CSS を使って OG 画像を生成できます。
- Static Export for App Router:Server Components に対する静的 / Single-Page Application (SPA) サポート。
- Parallel Routes と Interception:App Router 用の高度なルーティング機能。
今日アップデートするには次を実行してください:
npm i next@latest react@latest react-dom@latest eslint-config-next@latest
App Router を次のマイナーリリースで安定化(stable)としてマークするところまで来ており、今後はパフォーマンス最適化、挙動の改善、バグ修正に注力していきます。Mutations のような一部機能はまだ作業中ですが、他の App Router 機能の API サーフェスに影響を与えることは想定していません。App Router で皆さんが何を作るか楽しみにしており、フィードバックをお待ちしています。
File-Based Metadata API
Next.js 13.2 で導入した Metadata API により、layout や page から Metadata オブジェクトをエクスポートして title、meta、link タグ等の HTML head 内のメタデータを定義できるようになりました。
例:layout.js または page.js
export const metadata = {
title: 'Home',
};
export async function generateMetadata({ params, searchParams }) {
const product = await getProduct(params.id);
return { title: product.title };
}
export default function Page() {}
設定ベースの metadata に加えて、Metadata API は新しいファイル規約もサポートし、SEO やウェブ上での共有に便利なカスタマイズを簡単に行えるようになりました:
- opengraph-image.(jpg|png|svg)
- twitter-image.(jpg|png|svg)
- favicon.ico
- icon.(ico|jpg|png|svg)
- sitemap.(xml|js|jsx|ts|tsx)
- robots.(txt|js|jsx|ts|tsx)
- manifest.(json|js|jsx|ts|tsx)
例:アプリの favicon と /about ページ用の Open Graph 画像をファイルベースで追加する
app
├── favicon.ico
├── layout.js
├── page.js
└── about
├── opengraph-image.jpg
└── page.js
Next.js は本番環境でこれらのファイルをハッシュ付きファイル名で自動的に配信し(キャッシュ用)、アセットの URL、ファイルタイプ、画像サイズなどの正しいメタデータ情報で head 要素を更新します。
-
ルート「/」を訪問した場合
<link rel="icon" href="<computedUrl>" />
-
「/about」を訪問した場合
<link rel="icon" href="<computedUrl>" />
<meta property="og:image" content="<computedUrl>" type="<computedType>" ... />
静的ファイルを追加するのが最も簡単な方法ですが、動的にファイルを生成する必要がある場合もあります。各静的ファイル規約には、それを動的に生成するための (.js|.jsx|.ts|.tsx) バリアントが用意されています。例えば、静的な sitemap.xml を置くだけでなく、外部データソースから動的に生成されるページがあるケース向けに動的 sitemap を作成できます。
例:動的 sitemap(app/sitemap.js)
export default async function sitemap() {
const res = await fetch('https://.../posts');
const allPosts = await res.json();
const posts = allPosts.map((post) => ({
url: `https://acme.com/blog/${post.slug}`,
lastModified: post.publishedAt,
}));
const routes = ['', '/about', '/blog'].map((route) => ({
url: `https://acme.com${route}`,
lastModified: new Date().toISOString(),
}));
return [...routes, ...posts];
}
config ベースとファイルベースのオプションを組み合わせることで、静的および動的メタデータの両方を網羅する包括的な Metadata API が利用可能になります。Metadata API は 13.3 で App Router(app ディレクトリ)向けに利用可能です。pages ディレクトリでは利用できません。
Learn more about file-based metadata and view the API reference.
Dynamic Open Graph Image Generation
6 ヶ月前にリリースした @vercel/og と Satori は、JSX / HTML / CSS を使って動的に画像を生成できるライブラリです。@vercel/og は Next.js Conf で実際に使用され、参加者用のチケット画像を 100,000 枚以上動的に生成しました。多くの Vercel 顧客に採用され、リリース以来 900,000 回以上ダウンロードされたことを受け、外部パッケージを必要とせずに Next.js アプリケーションで動的生成画像を使えるようになりました。
次のように next/server から ImageResponse をインポートして画像を生成できます:
/app/about/opengraph-image.tsx
import { ImageResponse } from 'next/server';
export const size = { width: 1200, height: 600 };
export const alt = 'About Acme';
export const contentType = 'image/png';
export const runtime = 'edge';
export default function og() {
return new ImageResponse();
}
ImageResponse は Route Handlers やファイルベースの Metadata など他の Next.js API と自然に統合されます。たとえば、opengraph-image.tsx に ImageResponse を使えば、ビルド時またはリクエスト時に Open Graph や Twitter 用の画像を生成できます。
Learn more about the Image Response API.
Static Export for App Router
Next.js の App Router は完全な静的エクスポートをサポートするようになりました。最初に静的サイトまたは SPA として開始し、後でサーバーを必要とする Next.js 機能に任意でアップグレードできます。
next build を実行すると、Next.js はルートごとに HTML ファイルを生成します。厳密な SPA を個別の HTML ファイルに分割することで、クライアント側で不要な JavaScript を読み込む必要がなくなり、バンドルサイズを削減してページ読み込みを高速化できます。
例:next.config.js
/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
output: 'export',
}
module.exports = nextConfig
Static Export は app router の新機能(静的 Route Handlers、Open Graph 画像、React Server Components など)と動作します。Server Components はビルド中に実行され、従来の静的サイト生成と同様に初回ロード用の静的 HTML とクライアント間ナビゲーション用の静的ペイロードをレンダリングします。
以前は pages ディレクトリで Static Export を利用するには next export を実行する必要がありましたが、next.config.js で output: 'export' を設定すると next build は出力先に out ディレクトリを生成します。app router と pages ディレクトリの両方で同じ設定を使用できます。つまり next export はもはや必須ではありません。
高度な静的エクスポートサポートにより、開発プロセス(next dev)中に早い段階でエラーが出るようになります。たとえば cookies() や headers() のようにサーバーが必要な動的関数を使おうとするとエラーになります。
Learn more about Static Export.
Parallel Routes と Interception
Next.js 13.3 では Parallel Routes と Intercepting Routes という新しい動的規約が導入され、高度なルーティングケースを実装できるようになりました。これらの機能により、複雑なダッシュボードやモーダルのように同じビュー内で複数のページを表示できます。
Parallel Routes を使うと、同じビュー内で一度に複数のページをレンダリングし、それぞれ独立してナビゲートできます。条件に応じてページを切り替えてレンダリングする用途にも使えます。Parallel Routes は名前付きの「スロット」を使って作成され、@ フォルダ規約で定義します:
dashboard
├── @user
│ └── page.js
├── @team
│ └── page.js
├── layout.js
└── page.js
同じルートセグメント内の layout はスロットを props として受け取ります:
app/dashboard/layout.js
export default async function Layout({ children, user, team }) {
const userType = getCurrentUserType();
return (
<>
{userType === 'user' ? user : team}
{children}
</>
);
}
上の例では @user と @team の parallel route スロット(明示的スロット)がロジックに基づいて条件付きでレンダリングされています。children は暗黙のルートスロットであり @folder にマップする必要はありません。例えば dashboard/page.js は dashboard/@children/page.js と同等です。
Intercepting routes は現在のレイアウト内で新しいルートを読み込みつつブラウザの URL を「マスク」することを可能にします。フィードの中で写真をモーダルで開いてフィードをモーダルの背景に保持したい場合など、現在のページのコンテキストを維持することが重要なケースで便利です。Intercepting routes は相対パス ../ に似た (..) 規約で定義できます。また、(...) 規約を使って app ディレクトリに対する相対パスを作成することもできます。
feed
├── @modal
│ └── (..)photo
│ └── [id]
│ └── page.tsx
├── page.tsx
└── layout.tsx
photo
└── [id]
└── page.tsx
上の例では、ユーザーのプロフィールから写真をクリックするとクライアントサイドナビゲーション中にモーダルで写真が開きます。ただしリロードや共有の場合はその写真がデフォルトのレイアウトで読み込まれます。
Parallel routes と interception により Instagram のようなモーダルルーティングが可能になります。これにより、モーダルコンテンツを URL で共有可能にする、ページのリロード時にコンテキストが失われないようにする、履歴の戻る・進むでモーダルの閉開を扱う、といった課題を解決できます。
より多くの例や挙動については Parallel and Intercepting Routes のドキュメントを参照してください。
その他の改善点
- デザイン更新:Next.js のホームページとショーケースを新しいデザインに刷新しました。
- Turbopack:Middleware、全 next/font オプション、Server Components のストリーミングのサポートを追加(beta に向けて)。(デモを参照)
- next.config.js の Fast Refresh:next.config.js を変更するとローカルの dev サーバーが自動的に再起動します。.env、.env.*、jsconfig.json、tsconfig.json の自動リロードが拡張されました。
- アクセシビリティ:App Router に pages からのルートアナウンス機能を追加しました。これによりクライアントサイドのルート遷移がスクリーンリーダー等に通知されます。
- スタティック型付けされたリンク:next.config.js で設定した redirects と rewrites が型チェックの対象になります。
- create-next-app の Tailwind CSS:npx create-next-app@latest で新しいプロジェクトを始める際に Tailwind CSS をオプションで選択できるようになりました。--tailwind フラグでも指定可能で、プロジェクトが事前設定されます。
- Route Handlers:route.ts でサポートされた HTTP メソッドの代わりに export default を使うと、役に立つエラーが投げられるようになりました。
- 画像:next/image が fetchPriority="high" 属性をサポートしました。
- Metadata:13.2 で非推奨になっていた旧 API (head.js) は削除されました。代わりに組み込みの Metadata API を使用してください。
- ルーティングからフォルダを除外:フォルダ名を _ でプレフィックスすると、そのフォルダと子セグメントをルーティング対象から除外できます。例:app/_dashboard/page.tsx はルーティングされません。
- App Router:新しいクライアントコンポーネントフック useParams を追加し、該当するルートセグメントの動的パラメータを読み取れるようになりました。
- 改善されたスタイルシート読み込み:React の Suspensey CSS を実装し、特にナビゲーション時の CSS 読み込みや未スタイルコンテンツのフラッシュに関する多くの問題を解決しました。
- 改善された Not Found 処理:期待される notFound() エラーの捕捉に加えて、ルートの app/not-found.js ファイルはアプリ全体の未一致 URL も処理します。つまりアプリで扱われない URL を訪れたユーザーには app/not-found.js がエクスポートする UI が表示されます。
- 改善されたクライアントサイドルーターキャッシュ:router.refresh() はキャッシュ全体を無効化し、検索パラメータは保持されます。
Learn more.