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

2022年12月22日木曜日

Next.js 13.1

投稿者

Next.js 13.1では、pages/ (安定版) および app/ (ベータ版) ディレクトリの両方が改善されました

今すぐ次のコマンドを実行して更新してください

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

app ディレクトリの信頼性とサポートの向上

Next.js 13で、新しいappディレクトリ (ベータ版) を発表しました。この新しいルーティングおよびデータフェッチシステムは、既存のpagesディレクトリと並行して段階的に導入できます。

appディレクトリは、強化されたレイアウト、コンポーネント、テスト、スタイルの併置、コンポーネントレベルのデータフェッチなど、多くの利点を提供します。皆様からのフィードバックと早期テストのおかげで、appディレクトリの信頼性にいくつかの改善を加えました

  • レイアウトDivなし: 以前、appディレクトリはナビゲーション時にレイアウトをスクロール表示するために追加の<div>要素を追加していました。13.1では、これらの余分な要素は作成されなくなりました。スクロール動作は維持されます。
  • TypeScriptプラグイン: ページおよびレイアウトの設定オプションの提案、IDEへのドキュメントの直接表示、サーバーおよびクライアントコンポーネントに関する役立つ使用ヒント (サーバーコンポーネントでのuseStateの使用防止など) を提供する新しいTypeScriptプラグインを構築しました。詳細はこちら
  • 信頼性の改善: CSSモジュールサポートの改善、レイアウトとページにおけるcache()fetch()の正しい重複排除、メモリリークなど、多数のバグを修正しました。
  • クライアントサイドJavaScriptの削減: appディレクトリには、pagesディレクトリよりも9.3kB少ないクライアントサイドJavaScriptが含まれるようになりました。このベースラインは、アプリケーションにサーバーコンポーネントを1つ追加しても1000個追加しても増加しません。Reactランタイムは一時的にわずかに大きくなっていますが、この増加はNext.jsが以前処理していたメカニズムを扱うReact Server Componentsランタイムによるものです。これをさらに削減するよう取り組んでいます。
pages/app/差分
初回ロードJS合計ベースライン-9.3kB12.1%削減
Next.jsランタイムベースライン-12kB56.8%削減
Reactランタイムベースライン+2.7kB5.2%増加

appディレクトリの安定性向上の進捗を継続できることを嬉しく思います。appディレクトリのベータ版ドキュメントは、皆様のフィードバックに基づいて何百回も更新されています。

モジュールトランスパイルの組み込み (安定版)

ローカルパッケージ (モノレポなど) や外部依存関係 (node_modules) の依存関係を、トランスパイルおよびバンドル対象としてマークできるようになりました。この組み込みサポートは、人気のnext-transpile-modulesパッケージを置き換えるものです。

/** @type {import('next').NextConfig} */
const nextConfig = {
  transpilePackages: ['@acme/ui', 'lodash-es'],
};
 
module.exports = nextConfig;

このパッケージの開発に尽力し、組み込みサポートがコミュニティのニーズを満たしていることを確認する上で協力してくれたPierre de la Martinière (@martpie) に感謝いたします。

バンドルサイズ縮小のためのインポート解決

多くの人気npmパッケージは、他のモジュールを再エクスポートする単一のファイルを提供するために「バレルファイル」を利用しています。例えば

@acme/ui/index.ts
export { default as Button } from './dist/Button';
export { default as Slider } from './dist/Slider';
export { default as Dropdown } from './dist/Dropdown';

これにより、パッケージの利用者は単一行で名前付きエクスポートを使用できます

import { Button, Slider, Dropdown } from '@acme/ui';

バンドラーはこれらのバレルファイルを理解し、未使用の再エクスポート (「デッドコード排除」と呼ばれる) を削除できますが、このプロセスには再エクスポートされたすべてのファイルのパース/コンパイルが含まれます。公開されているライブラリの中には、何千ものモジュールが再エクスポートされているバレルファイルを同梱しているnpmパッケージもあり、これがコンパイル時間を遅くする原因となります。これらのライブラリは、この問題を回避するためにbabel-plugin-transform-importsを推奨していましたが、SWCを使用している場合は以前サポートがありませんでした。Next.jsにmodularizeImportsと呼ばれる新しいSWCトランスフォームを組み込みました。

この新しい設定により、定義されたパターンに基づいてインポートステートメントを変更するSWCトランスフォームが有効になります。例えば、3つのコンポーネントを使用するための上記のコードは、開発者が手動で記述することなく、自動的に直接インポートを使用するように変換されます

// Before (with barrel file)
import { Button, Slider, Dropdown } from '@acme/ui';
 
// After (with modularized imports from plugin)
import Button from '@acme/ui/dist/Button';
import Slider from '@acme/ui/dist/Slider';
import Dropdown from '@acme/ui/dist/Dropdown';

この変換は、next.config.jsmodularizeImportsオプションで可能です

next.config.js
module.exports = {
  modularizeImports: {
    '@acme/ui': {
      transform: '@acme/ui/dist/{{member}}',
    },
  },
};

@mui/icons-materiallodashでこのトランスフォームを活用することで、未使用ファイルのコンパイルをスキップできます。詳細はこちら

実際の動作を見るためにデモを見る

Edge向けの軽量Node.jsランタイム、APIルートで安定版に

Next.js内のEdge Runtimeは、Node.js APIの厳密なサブセット(RequestResponseなど)を使用しており、VercelのようなEdgeコンピューティングプラットフォームやセルフホスティングの場合と互換性があります。これらのAPIはブラウザを含め、どこでも実行できるため、開発者は一度学習すればどこでも記述できます。

pages/api/hello.ts
// "experimental-" prefix is no longer needed
export const config = {
  runtime: 'edge',
};
 
export default function handler(req: Request) {
  return new Response('Hello World');
}

Next.js Middlewareは、より良いパフォーマンスのために、デフォルトでこの軽量なEdgeランタイムをすでに使用しています。Middlewareはアプリケーションのすべてのリクエストの前に実行できるため、低レイテンシーを確保するには軽量なランタイムが不可欠です。Next.js 12.2では、APIルートでもこのランタイムを任意で使用する機能を追加しました。

13.1では、Next.js内のEdge RuntimeがAPIルートで安定版になりました。セルフホスティングの場合、Edge Runtimeを使用するMiddlewareとAPIルートは、デフォルトでnext startの一部として単一リージョンのワークロードとして実行されます。Vercelでは、Next.js MiddlewareとAPIルートは、可能な限り低いレイテンシーのためにVercel Edge Functionsを使用してグローバルにデプロイされます。Vercel Edge Functionsも現在一般公開されています。

Turbopackの改善

Next.js 13でTurbopackアルファ版をリリースして以来、信頼性の向上、最も要望の多かった機能のサポート追加、および他のフレームワークでのプラグインと使用に関する計画策定に注力してきました。

Next.js 13.0.0以降、Turbopackは

  • PostCSS(Tailwind CSSを含む)をサポート
  • next/imageをサポート
  • @next/font(Google Fonts)をサポート
  • 動的なimport()ステートメントからのCSS読み込みをサポート
  • CSSソースマップをサポート(貢献してくれた@ahabhgkに感謝します)
  • next devエラーオーバーレイでのエラー処理を改善
  • メモリ使用量を改善
  • CSSモジュールサポートを改善
  • HMRアップデートのチャンクアルゴリズムを改善
  • HMRソースマップの信頼性を改善

Evan You氏とViteコミュニティの皆様からのフィードバックと貢献に感謝いたします。これにより、Turbopackのベンチマークを可能な限り正確なものにすることができました。Viteチームと協力し、最新のTurbopackベンチマークを検証し、テスト方法論に数多くの改善を加えました。

この協力の結果、Reactの更新メカニズムにかかる時間を含む、より正確な測定基準を使用するようになりました。Turbopackおよびwebpack上のNext.js 13.1で、React Fast Refreshの時間を30ms改善することができました。また、SWCを使用したViteの新しいベンチマークも追加しました。これは、Babelを使用したデフォルトのViteと比較してパフォーマンスが向上していることを示しています。更新されたベンチマークを見るか、テスト方法論について読んでください。

next dev --turboでNext.js 13のTurbopackアルファ版を今すぐ試してみてください。フィードバックがある場合は、GitHubディスカッションでお知らせください。

Next.jsの高度なMiddleware

皆様からのフィードバックのおかげで、Next.js Middlewareはこれまで以上に強力になりました。13.1では、Middlewareからレスポンスを返すだけでなく、リクエストにヘッダーを設定できるようになりました。

これらのAPIの改善により、Next.jsルーティングライフサイクルのあらゆる部分をカスタマイズするための強力な新しい柔軟性が提供されます。next.config.js内のexperimental.allowMiddlewareResponseBody設定オプションは不要になりました。

リクエストにヘッダーをより簡単に設定できるようになり、またrewriteredirectすることなく直接応答できるようになりました

middleware.ts
import { NextResponse } from 'next/server';
 
export function middleware(request: Request) {
  // Check if a user has access...
  if (!isAuthorized(request)) {
    return NextResponse.json({ message: 'Unauthorized' });
  }
 
  // Add a new header, this will change the incoming request headers
  // that you can read in getServerSideProps and API routes
  const requestHeaders = new Headers(request.headers);
  requestHeaders.set('x-version', '13.1');
 
  return NextResponse.next({
    request: {
      // Apply new request headers
      headers: requestHeaders,
    },
  });
}

Next.jsの高度なMiddlewareについて詳しくはこちら。

その他の改善

  • @next/fontは、同じフォント宣言で複数のフォントウェイトとスタイルを追加できるようになりました。詳細はこちら
  • next/dynamicはReactのプリミティブであるlazy()<Suspense>を使用するようになりました。以前のsuspenseオプションは不要になりました。これらの変更により、next/dynamicappディレクトリと互換性があります。
  • create-next-appが新しいデザインに更新され、レイアウトシフトなしでフォントの自動セルフホスティングを可能にする@next/fontがデフォルトで含まれるようになりました。npx create-next-app@latestで試すか、テンプレートをデプロイしてください。
  • Next.js 13のappディレクトリ (ベータ版) の最新機能と慣習の一部を紹介するApp Directory Playgroundに数多くの改善を加えました。ご自身でデプロイしてください。
  • 画像プレースホルダー、遅延ロード、自動最適化、キーボードサポートなどを含む高性能画像ギャラリーテンプレートを作成しました。ご自身でデプロイしてください。
  • 大規模なオープンソースのReactおよびExpress.jsアプリケーションをNext.jsに移行する方法を理解するためのリソースを作成しました。これには詳細なウォークスルーと特定のコミットへのリンクが含まれます。

コミュニティ

Next.jsは、2,400人を超える個人開発者、GoogleやMetaのような業界パートナー、そしてVercelのコアチームの共同作業の結果です。週に360万回以上のnpmダウンロードと97,900以上のGitHubスターを獲得しており、Next.jsはウェブ構築において最も人気のある方法の1つです。

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

このリリースは以下によって提供されました

そして、以下の皆様の貢献に感謝いたします: @aarnadlr, @aaronbrown-vercel, @aaronjy, @abayomi185, @ademilter, @adictonator, @adilansari, @adtc, @alantoa, @aleksa-codes, @alfred-mountfield, @alpha-xek, @andarist, @andykenward, @anujssstw, @artdevgame, @artechventure, @arturbien, @aziyatali, @bennettdams, @bertho-zero, @blue-devil1134, @bot08, @brkalow, @brvnonascimento, @chanceaclark, @chibicode, @chrisipanaque, @chunsch, @colinking, @craigwheeler, @ctjlewis, @cvolant, @danmindru, @davidnx, @delbaoliveira, @devvspaces, @dtinth, @ducanhgh, @duncanogle, @ethomson, @fantaasm, @feugy, @fomichroman, @gruz0, @haschikeks, @hughlilly, @idoob, @iiegor, @imranbarbhuiya, @ingovals, @inokawa, @ishaqibrahimbot, @ismaelrumzan, @jakemstar, @janicklas-ralph, @jaredpalmer, @jaykch, @jimcresswell, @joliss, @josephcsoti, @joshuaslate, @joulev, @jueungrace, @juliusmarminge, @karlhorky, @kikobeats, @kleintorres, @koenpunt, @koltong, @kosai106, @labyrinthitis, @lachlanjc, @laityned, @leerob, @leoortizz, @lorenzobloedow, @lucasassisrosa, @m7yue, @manovotny, @marcus-rise, @matthew-heath, @mattpr, @maxleiter, @maxproske, @meenie, @mmaaaaz, @mnajdova, @moetazaneta, @mrkldshv, @nathanhammond, @nekochantaiwan, @nfinished, @niedziolkamichal, @nocell, @notrab, @nuta, @nutlope, @obusk, @orionmiz, @peraltafederico, @reshmi-sriram, @reyrodrigez, @rightones, @rishabhpoddar, @saseungmin, @serkanbektas, @sferadev, @silvioprog, @sivtu, @soonoo, @sqve, @steven-tey, @sukkaw, @superbahbi, @teobler, @theevilhead, @thomasballinger, @timeyoutakeit, @valentinh, @ws-jm, @wxh06, @yasath, @yutsuten, and @zekicaneksi。