コンテンツにスキップ
ブログに戻る

2023年4月6日 木曜日

Next.js 13.3

投稿者

Next.js 13.3では、以下のような人気のコミュニティからの要望に応える機能が追加されました。

本日、実行してアップデートしてください

ターミナル
npm i next@latest react@latest react-dom@latest eslint-config-next@latest

次のマイナーリリースでApp Routerを安定版としてマークすることに近づいており、パフォーマンスの最適化、動作の改善、バグ修正に注力しています。

Mutationsのような一部の機能はまだ開発中ですが、これらが他のApp Router機能のAPIサーフェスに影響を与えることは想定していません。App Routerで皆様が構築されるものを見るのが楽しみであり、フィードバックをお待ちしております

ファイルベースのメタデータAPI

Next.js 13.2では、メタデータAPI(例:titlemetalinkタグをHTMLのhead要素内に定義する)を発表しました。これは、レイアウトまたはページからメタデータオブジェクトをエクスポートすることでメタデータを定義できます。

layout.js または page.js
// either Static metadata
export const metadata = {
  title: 'Home',
};
// Output:
// <head>
//	 <title>Home</title>
// </head>
 
// or Dynamic metadata
export async function generateMetadata({ params, searchParams }) {
  const product = await getProduct(params.id);
  return { title: product.title };
}
// Output:
// <head>
//	 <title>My Unique Product</title>
// </head>
 
export default function Page() {}

構成ベースのメタデータに加えて、メタデータAPIは新しいファイル規約をサポートし、SEOとWebでの共有を改善するためにページを便利にカスタマイズできます。

  • 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)

例えば、ファイルベースのメタデータを使用して、アプリにファビコンを追加したり、/aboutページにOG画像を追加したりできます。

app
├── favicon.ico
├── layout.js
├── page.js
└── about
    ├── opengraph-image.jpg
    └── page.js

Next.jsは、本番環境でこれらのファイルをハッシュ付き(ファイル名に)で自動的に提供し、キャッシュのために、アセットのURL、ファイルタイプ、画像サイズなどの関連head要素を正しいメタデータ情報で更新します。

// Visiting "/"
<link rel="icon" href="<computedUrl>"/>
 
// Visiting "/about"
<link rel="icon" href="<computedUrl>"/>
<meta property="og:image" content="<computedUrl>" type="<computedType>" ... />

静的ファイルをアプリケーションに追加するのは最も簡単なアプローチであることが多いですが、動的にファイルを作成する必要がある場合もあります。静的ファイル規約ごとに、ファイルを作成するコードを記述できる動的な(.js|.jsx|.ts|.tsx)バリアントが付属しています。

例えば、静的なsitemap.xmlファイルを追加できますが、ほとんどのサイトでは外部データソースを使用して動的に生成されるページがあります。動的なサイトマップを生成するには、動的ルートの配列を返すsitemap.jsファイルを追加できます。

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];
}

構成ベースと新しいファイルベースのオプションにより、静的と動的なメタデータの両方をカバーする包括的なメタデータAPIが利用できます。

メタデータAPIは、App Router(app)では13.3で利用可能です。pagesディレクトリでは利用できません。ファイルベースのメタデータについてさらに学習し、APIリファレンスを表示してください。

動的なOpen Graph画像生成

6ヶ月前、@vercel/ogSatoriをリリースしました。これらは、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やファイルベースのメタデータなど、他のNext.js APIと自然に連携します。例えば、opengraph-image.tsxファイルでImageResponseを使用して、ビルド時またはリクエスト時に動的にOpen Graph画像とTwitter画像を生成できます。

Image Response APIについてさらに学習してください。

App Routerの静的エクスポート

Next.js App Routerは、完全に静的なエクスポートをサポートするようになりました。

静的なサイトまたはシングルページアプリケーション(SPA)として開始し、後でサーバーを必要とするNext.js機能を使用するためにオプションでアップグレードできます。

next build を実行すると、Next.js はルートごとに HTML ファイルを生成します。厳密な SPA を個別の HTML ファイルに分割することで、Next.js はクライアントサイドで不要な JavaScript コードを読み込むのを回避でき、バンドルサイズを縮小し、ページロードを高速化できます。

next.config.js
/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  output: 'export',
};
 
module.exports = nextConfig;

静的エクスポートは、静的なRoute Handlers、Open Graph画像、React Server Componentsを含むApp Routerの新しい機能と連携します。

例えば、Server Componentsはビルド中に実行され、従来の静的サイトジェネレーションと同様に、初期ページロード用の静的HTMLとルート間のクライアントナビゲーション用の静的ペイロードにレンダリングされます。

以前は、pagesディレクトリで静的エクスポートを使用するには、next exportを実行する必要がありました。しかし、next.config.jsオプションで、output: 'export'が設定されている場合、next buildoutディレクトリを出力します。App Routerとpagesディレクトリで同じ構成を使用できます。これは、next exportが不要になったことを意味します。

高度な静的エクスポートサポートにより、開発プロセス(next dev)の早い段階でエラーが発生します。例えば、cookies()headers()のようなサーバーを必要とする動的な関数を使用しようとした場合などです。

静的エクスポートについてさらに学習してください。

Parallel RoutesとInterception

Next.js 13.3では、高度なルーティングケース、つまり**Parallel RoutesとIntercepting Routes**を実装できる新しい動的な規約が導入されました。これらの機能により、複雑なダッシュボードやモーダルなど、同じビューに複数のページを表示できます。

Parallel Routesを使用すると、独立してナビゲートできる1つ以上のページを*同じビュー*で同時にレンダリングできます。条件付きでページをレンダリングするためにも使用できます。

Parallel Routesは、名前付き**「スロット」**を使用して作成されます。スロットは@folder規約で定義されます。

dashboard
├── @user
   └── page.js
├── @team
   └── page.js
├── layout.js
└── page.js

同じルートセグメントのレイアウトは、スロットをプロップとして受け入れます。

app/dashboard/layout.js
export default async function Layout({ children, user, team }) {
  const userType = getCurrentUserType();
 
  return (
    <>
      {userType === 'user' ? user : team}
      {children}
    </>
  );
}

上記の例では、@user@teamのParallel Routesスロット(明示的)は、ロジックに基づいて条件付きでレンダリングされます。childrenは、@folderにマッピングする必要がない暗黙のルートスロットです。例えば、dashboard/page.jsdashboard/@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 and interception enable Instagram-like modal routing.
Parallel RoutesとInterceptionにより、Instagramのようなモーダルルーティングが可能になります。

これは、モーダルを作成する際の課題、つまりモーダルのコンテンツをURL経由で共有可能にしたり、ページをリフレッシュしたときにコンテキストが失われるのを防いだり、バックスペースとフォワードナビゲーションでモーダルを閉じたり開いたりしたりする課題を解決します。

さらに多くの例と動作については、ParallelとIntercepting Routesのドキュメントを参照してください。

その他の改善点

  • デザインアップデート: Next.jsのホームページとショーケースは、新しいデザインでリフレッシュされました。
  • Turbopack: ミドルウェア、すべてのnext/fontオプション、Server Componentsのストリーミングサポートが追加され、ベータ版に近づいています(デモを見る)。また、vercel.comnextjs.orgのような成熟したNext.jsアプリでドッグフーディング中に発見された追加のバグも修正しました。Turbopackについてさらに学習してください。
  • next.config.jsのFast Refresh: next.config.jsの変更により、ローカル開発サーバーが自動的に再起動されるようになりました。これは、.env.env.*jsconfig.jsontsconfig.json構成ファイルの自動リロードを拡張します。
  • アクセシビリティ: App Routerには、pagesからのルートアナウンスが含まれるようになりました。この機能は、クライアントサイドのルート遷移をスクリーンリーダーやその他の支援技術にアナウンスします。アクセシビリティについてさらに学習してください。
  • 型指定されたリンクnext.config.jsで設定されたredirectsrewritesは、型チェック中に考慮されるようになりました。型指定されたリンクについてさらに学習してください。
  • create-next-appのTailwind CSS: npx create-next-app@latestで新しいプロジェクトを開始する際に、オプションでTailwind CSSを選択するか、--tailwindフラグを使用すると、このスタイリングソリューションでアプリケーションを事前構成できます。
  • Route Handlers: サポートされているHTTP動詞の代わりにexport defaultを使用すると、route.tsで役立つエラーが発生するようになりました。Route Handlersについてさらに学習してください。
  • 画像: next/imagefetchPriority="high"属性をサポートするようになりました。
  • メタデータ: メタデータの以前のAPI(head.js)は、13.2で非推奨になり、削除されました。代わりに、メタデータAPIを介してSEOの組み込みサポートを使用してください。
  • ルーティングからフォルダを除外する: フォルダの前に_を付けると、そのフォルダとその子セグメントはルーティングから除外されます。例えば、app/_dashboard/page.tsxはルーティング可能ではありません。
  • App Router: ルートセグメントの動的パラメーターを読み取るための新しいクライアントコンポーネントフックuseParamsが追加されました。使用方法についてさらに学習してください。
  • スタイルシート読み込みの改善: Next.jsはReactのSuspensey CSSを実装するようになり、CSS読み込みとスタイル未適用コンテンツのフラッシュに関する多くの問題を解決しました。特にナビゲーション中に顕著です。
  • Not Foundハンドリングの改善: 予期されるnotFound()エラーをキャッチすることに加えて、ルートのapp/not-found.jsファイルは、アプリケーション全体で一致しないURLも処理します。これは、アプリで処理されないURLにアクセスしたユーザーには、app/not-found.jsファイルによってエクスポートされたUIが表示されることを意味します。さらに学習してください。
  • クライアントサイドルーターキャッシュの改善: router.refresh()はキャッシュ全体を無効にするようになり、検索パラメーターがキャッシュキーの一部になるため、2つの検索パラメーター間(例:/?search=leerob/?search=tim)のナビゲーションで、パラメーターに依存するコンテンツが正しく復元されるようになります。

コミュニティ

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

GitHub Discussions、Reddit、Discordでコミュニティに参加してください。

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

  • Next.jsチーム:Andrew、Balazs、Hannes、Jan、Jiachi、Jimmy、JJ、Josh、Sebastian、Shu、Steven、Tim、Wyatt。
  • Turbopackチーム:Alex、Donny、Justin、Leah、LongYinan、Maia、OJ、Tobias、Will。

そして、@shuding、@huozhi、@sokra、@hanneslund、@JesseKoldewijn、@kaguya3222、@yangshun、@ijjk、@konomae、@Brooooooklyn、@jridgewell、@zlrlyy、@JohnDaly、@abhiyandhakal、@benjie、@johnnyomair、@nk980113、@dirheimerb、@DerTimonius、@DuCanhGH、@padmaia、@stafyniaksacha、@Gladowar、@zek、@jankaifer、@styfle、@balazsorban44、@wbinnssmith、@chibicode、@ForsakenHarmony、@franktronics、@FSaldanha、@Schniz、@raisedadead、@AdamKatzDev、@wyattjoh、@leerob、@meesvandongen、@vladikoff、@feedthejim、@tka5、@pyjun01、@gdborton、@M3kH、@aretrace、@shivanshubisht、@alexkirsz、@agrattan0820、@vinaykulk621、@heyitsuzair、@mrkldshv、@timneutkens、@furkanmavili、@swaminator、@EndangeredMassa、@DevEsteves、@rishabhpoddar、@schehata、@molebox、@dlehmhus、@akshaynox、@sp00ls、@janicklas-ralph、@tomryanx、@kwonoj、@karlhorky、@kdy1、@dante-robinson、@lachlanjc、@ianmacartney、@hotters、@isaackatayev、@insik-han、@jayair、@ivanhofer、@javivelasco、@SukkaW、@visshaljagtap、@imranbarbhuiya、@nivak-monarch、@HarshaVardhanReddyDuvvuru、@ianldgs、@ricardofiorani、@swarnava、そして@gustavostzの貢献。