Back to Blog — 火曜日, 2022-10-25
投稿者: Balázs Orbán (@balazsorban44), Delba de Oliveira (@delba_oliveira), DongYoon Kang (@kdy1dev), Jiachi Liu (@huozhi), JJ Kasper (@ijjk), Lee Robinson (@leerob), Maia Teegarden (@padmaia), Sebastian Markbåge (@sebmarkbage), Shu Ding (@shuding), Steven (@styfle), Tim Neutkens (@timneutkens)
Next.js 13
発表どおり、Next.js 13(stable)は“制限のないダイナミック性”の基盤を築きます:
- app Directory (beta): より簡単に、より高速に、クライアント側 JS を減らす。
- Layouts
- React Server Components
- Streaming
- Turbopack (alpha): Rust ベースの Webpack 置換え。最大で 700x 高速化。
- 新しい next/image: ネイティブブラウザの遅延読み込みで高速化。
- 新しい @next/font (beta): レイアウトシフトゼロの自動セルフホスティングフォント。
- 改良された next/link: 自動で <a> を出力する簡素化された API。
Next.js 13 と pages ディレクトリは安定しており、本番利用可能です。次のコマンドで今すぐアップデートできます:
npm i next@latest react@latest react-dom@latest eslint-config-next@latest
新しい app Directory (Beta)
今回、ルーティングとレイアウト体験を改善し、React の将来に合わせて app ディレクトリを導入します。これは以前にコミュニティ向けに公開した Layouts RFC のフォローアップです。app ディレクトリは現在ベータ段階であり、まだ本番への導入は推奨しません。
Next.js 13 は pages ディレクトリでも動作し、改善された next/image と next/link などの安定機能を利用できます。app ディレクトリは段階的に導入可能で、pages ディレクトリは当面サポートされ続けます。
app ディレクトリは以下をサポートします:
- Layouts: ルート間で UI を簡単に共有し、状態を保持して高コストな再レンダリングを回避。
- Server Components: 最もダイナミックなアプリケーションでサーバーファーストをデフォルトに。
- Streaming: ローディング状態を即座に表示し、レンダリングされた UI 単位をストリーミング。
- データフェッチのサポート: async Server Components と拡張された fetch API でコンポーネント単位のフェッチを可能に。
既存の pages/ ディレクトリから app/ を段階的に採用できます。
Layouts
app/ ディレクトリは、ナビゲーション間で状態を維持しつつ複雑なインターフェースをレイアウトするのを簡単にします。ネストしたレイアウトが可能で、コンポーネント、テスト、スタイルなどのアプリケーションコードをルートと共にコロケートできます。app/ は pages/ から段階的に移行できます。
app/ 内でルートを作成するには単一ファイル page.js が必要です:
app/page.js
export default function Page () {
return <h1>Hello, Next.js!</h1>;
}
ファイルシステムを通じてレイアウトを定義できます。Layouts は複数ページ間で UI を共有し、ナビゲーション時に状態を保持し、対話性を維持して再レンダリングを行いません。
app/blog/layout.js
export default function BlogLayout ({ children }) {
return <section>{children}</section>;
}
詳しくは layouts と pages について学ぶか、サンプルをデプロイして試してみてください。
Server Components
app/ ディレクトリは React の新しい Server Components アーキテクチャをサポートします。Server Components と Client Components はそれぞれ得意な場所(サーバーとクライアント)を使い分けることで、単一のプログラミングモデルで高速かつ高い対話性を持つアプリを構築できます。
Server Components により、クライアントへ送る JavaScript の量を削減して初期表示を高速化するための基盤を整えています。ルートが読み込まれると、Next.js と React のランタイムがロードされますが、これはキャッシュ可能でサイズが予測可能です。アプリケーションが大きくなってもランタイムサイズは増加しません。さらにこのランタイムは非同期に読み込まれ、サーバーからの HTML がクライアント上で徐々に強化されます。
Server Components の詳細やサンプルのデプロイもご覧ください。
Streaming
app/ ディレクトリは、レンダリング済みの UI 単位を逐次的にクライアントへストリーミングする機能を導入します。Server Components とネストしたレイアウトを組み合わせることで、データを明示的に必要としないページの部分は即座に表示し、データ取得中の部分はローディング状態を表示できます。このアプローチにより、ユーザーはページ全体が読み込まれるのを待たずに操作を開始できます。
アプリケーションコード(コンポーネント、テスト、スタイルなど)をルートと共にコロケートできます。Vercel にデプロイした場合、app/ を使用する Next.js 13 アプリは Node.js と Edge 両方のランタイムで既定でレスポンスをストリーミングします。
詳細やサンプルのデプロイを参照してください。
データフェッチ
React の Support for Promises RFC により、コンポーネント内でデータを取得しプロミスを扱う強力な方法が導入されました:
app/page.js
async function getData () {
const res = await fetch('https://api.example.com/...');
return res.json();
}
export default async function Page () {
const data = await getData();
return <main>{ /* ... */ }</main>;
}
React と Next.js ではネイティブの fetch Web API も拡張されています。fetch は自動的にリクエストの重複排除を行い、コンポーネントレベルでのフェッチ、キャッシュ、再検証を柔軟に行える単一の方法を提供します。これにより、Static Site Generation(SSG)、Server-Side Rendering(SSR)、Incremental Static Regeneration(ISR)の利点が一つの API で利用可能になります:
fetch(URL, { cache: 'force-cache' });
fetch(URL, { cache: 'no-store' });
fetch(URL, { next: { revalidate: 10 } });
app ディレクトリでは、layouts、pages、components の中でデータをフェッチでき、サーバーからのストリーミングレスポンスもサポートします。ローディングやエラー状態の扱いをエルゴノミクス的に改善し、レンダリングされる UI をストリームで送る方法を提供します。将来のリリースではデータのミューテーション(変更)についても改善と簡素化を行う予定です。
また、app/ ディレクトリでは新しい特別なファイル loading.js を使って Suspense 境界で Instant Loading UI を自動生成できます。
コミュニティ、パッケージメンテナ、React エコシステムの他社と協力して、この新しい React と Next.js の時代に向けて構築していくことを楽しみにしています。コンポーネント内にデータフェッチをコロケートし、クライアントへ送る JavaScript を削減する能力は、app/ ディレクトリに対する重要なコミュニティフィードバックの一部でした。
詳しくはデータフェッチについて学ぶか、サンプルをデプロイして試してください。
Turbopack の紹介(Alpha)
Next.js 13 には Turbopack が含まれます。Turbopack は Rust ベースの Webpack の後継です。Webpack は 30 億回以上ダウンロードされていますが、JavaScript ベースのツールで到達できる最大性能に限界があります。
Next.js 12 で我々はネイティブな Rust ベースのツールへの移行を開始しました。まず Babel を置き換え、トランスパイルが 17x 高速化しました。次に Terser を置き換え、ミニファイが 6x 高速化しました。今こそバンドルについてもネイティブに踏み切る時です。
Next.js 13 で Turbopack(alpha)を使うと以下が得られます:
- Webpack より 700x 速い更新
- Vite より 10x 速い更新
- Webpack より 4x 速いコールドスタート
Turbopack は大規模アプリでの HMR を 700x 高速化する Rust ベースの Webpack 後継です。開発時には必要最小限のアセットのみをバンドルするため、起動時間が非常に速いです。3,000 モジュールのアプリケーションでは Turbopack の起動は 1.8 秒、Vite は 11.4 秒、Webpack は 16.5 秒です。
Turbopack は Server Components、TypeScript、JSX、CSS などを標準でサポートします。アルファ期間中は多くの機能が未対応のため、ご意見をぜひお聞かせください。
注意: Next.js における Turbopack は現時点で next dev のみサポートしています。対応機能一覧を参照してください。next build 向けサポートも追加中です。
今日から次のコマンドで Turbopack アルファを試せます:
next dev
next/image
Next.js 13 は強力な新しい Image コンポーネントを導入します。これにより、レイアウトシフトなしで画像を簡単に表示し、オンデマンドでファイルを最適化してパフォーマンスを向上できます。Next.js コミュニティ調査では、回答者の 70% が本番で Next.js Image コンポーネントを使用しており、Core Web Vitals の改善を確認しています。
新しい Image コンポーネントの特徴:
- クライアント側の JavaScript をより少なく出力
- スタイリングと設定が容易
- デフォルトで alt タグを必須にしてアクセシビリティを向上
- Web プラットフォームと整合
- ネイティブの遅延読み込みによりハイドレーション不要で高速
例:
app/page.js
import Image from 'next/image';
import avatar from './lee.png';
export default function Home () {
return <Image alt="leeerob" src={avatar} placeholder="blur" />;
}
詳しくは Image コンポーネントについて学ぶか、サンプルをデプロイして試してください。
next/image のアップグレード
古い Image コンポーネントは next/legacy/image に名前が変更されました。既存の next/image の使用を自動で next/legacy/image に更新する codemod を用意しています。例えばルートから以下を実行すると ./pages ディレクトリに対して codemod を実行します:
npx @next/codemod next-image-to-legacy-image ./pages
codemod の詳細を参照してください。
@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
next/link はもはや手動で <a> を子として追加する必要はありません。これは 12.2 で実験的に追加され、今回デフォルトになりました。Next.js 13 では <Link> が常に <a> をレンダリングし、基底タグへプロップを転送できます。例えば:
import Link from 'next/link';
<Link href="/about"><a>About</a></Link>
<Link href="/about">About</Link>
詳しくはドキュメントを参照してください。