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

2023年10月26日 木曜日

Next.js 14

投稿者

Next.js Confで発表したように、Next.js 14は、次の機能に焦点を当てた最も集中的なリリースです。

  • Turbopack: App & Pages Routerで5,000件のテストに合格
    • ローカルサーバーの起動が53%高速化
    • Fast Refreshによるコード更新が94%高速化
  • Server Actions (Stable): プログレッシブエンハンスメントされたミューテーション
    • キャッシュ & 再検証と統合されています。
    • シンプルな関数呼び出し、またはフォームとネイティブに動作します。
  • Partial Prerendering (Preview): 高速な初期静的レスポンス + ストリーミング動的コンテンツ
  • Next.js Learn (New): App Router、認証、データベースなどを教える無料コース。

今日アップグレードするか、以下から始めましょう。

ターミナル
npx create-next-app@latest

Next.js Compiler: Turbocharged

Next.js 13以降、Pages RouterとApp Routerの両方でローカル開発のパフォーマンスを向上させるために取り組んできました。

以前は、この取り組みをサポートするためにnext devやNext.jsの他の部分を書き直していました。その後、アプローチをより段階的に変更しました。これは、Rustベースのコンパイラがまもなく安定版になることを意味します。これは、まずすべてのNext.js機能をサポートすることに焦点を再設定したためです。

next devの5,000件の統合テストが、Turbopack(当社の基盤となるRustエンジン)で合格しました。これらのテストには、7年間のバグ修正と再現が含まれています。

vercel.com(大規模なNext.jsアプリケーション)でテストしたところ、次の結果が得られました。

  • ローカルサーバーの起動が最大53.3%高速化
  • Fast Refreshによるコード更新が最大94.7%高速化

このベンチマークは、大規模なアプリケーション(および大規模なモジュールグラフ)で期待されるパフォーマンス向上の実際の結果です。next devのテストの90%が合格したため、next dev --turboを使用すると、一貫して高速で信頼性の高いパフォーマンスが得られるはずです。

テストの合格率が100%になったら、今後のマイナーリリースでTurbopackを安定版にします。カスタム構成やエコシステムプラグインには、引き続きwebpackの使用をサポートします。

areweturboyet.comで、合格率のパーセンテージを確認できます。

フォームとミューテーション

Next.js 9では、API Routesが導入されました。これは、フロントエンドコードと並行してバックエンドエンドポイントを迅速に構築する方法です。

たとえば、api/ディレクトリに新しいファイルを作成します。

pages/api/submit.ts
import type { NextApiRequest, NextApiResponse } from 'next';
 
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse,
) {
  const data = req.body;
  const id = await createItem(data);
  res.status(200).json({ id });
}

次に、クライアント側では、ReactとonSubmitのようなイベントハンドラを使用してAPI Routeへのfetchを行うことができます。

pages/index.tsx
import { FormEvent } from 'react';
 
export default function Page() {
  async function onSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
 
    const formData = new FormData(event.currentTarget);
    const response = await fetch('/api/submit', {
      method: 'POST',
      body: formData,
    });
 
    // Handle response if necessary
    const data = await response.json();
    // ...
  }
 
  return (
    <form onSubmit={onSubmit}>
      <input type="text" name="name" />
      <button type="submit">Submit</button>
    </form>
  );
}

Next.js 14では、データミューテーションの作成における開発者エクスペリエンスを簡素化したいと考えています。さらに、ユーザーがネットワーク接続が遅い場合や、低電力デバイスからフォームを送信する場合のユーザーエクスペリエンスを向上させたいと考えています。

Server Actions (Stable)

API Routeを手動で作成する必要がないとしたらどうでしょう。代わりに、Reactコンポーネントから直接安全にサーバーで実行される関数を定義できます。

App RouterはReactのcanaryチャネル上に構築されており、これはフレームワークが新しい機能を採用するのに安定しています。v14現在、Next.jsは最新のReact canaryにアップグレードしており、これには安定したServer Actionsが含まれています。

Pages Routerの前の例は、1つのファイルに簡略化できます。

app/page.tsx
export default function Page() {
  async function create(formData: FormData) {
    'use server';
    const id = await createItem(formData);
  }
 
  return (
    <form action={create}>
      <input type="text" name="name" />
      <button type="submit">Submit</button>
    </form>
  );
}

Server Actionsは、過去にサーバー中心のフレームワークを使用したことがある開発者には馴染み深いものになるはずです。フォームやFormData Web APIなどのWebの基本の上に構築されています。

フォームを介したServer Actionsの使用はプログレッシブエンハンスメントに役立ちますが、必須ではありません。フォームなしで関数として直接呼び出すこともできます。TypeScriptを使用すると、クライアントとサーバー間で完全なエンドツーエンドの型安全性が得られます。

データの変更、ページの再レンダリング、またはリダイレクトは1回のネットワークラウンドトリップで発生する可能性があり、アップストリームプロバイダーが遅くても正しいデータがクライアントに表示されることを保証します。さらに、さまざまなアクションを構成して再利用でき、同じルートで多くの異なるアクションを含めることができます。

キャッシュ、再検証、リダイレクトなど

Server Actionsは、App Routerモデル全体に深く統合されています。次のことができます。

  • revalidatePath()またはrevalidateTag()を使用してキャッシュされたデータを再検証する
  • redirect()を介して異なるルートにリダイレクトする
  • cookies()を介してCookieを設定および読み取る
  • useOptimistic()で楽観的なUI更新を処理する
  • useFormState()でサーバーからのエラーをキャッチして表示する
  • useFormStatus()でクライアントにローディング状態を表示する

Server Actionsを使用したフォームとミューテーションまたはセキュリティモデルとServer ComponentsおよびServer Actionsのベストプラクティスについてさらに学ぶことができます。

Partial Prerendering (Preview)

Next.jsで開発中の、動的コンテンツのためのコンパイラ最適化であり、高速な初期静的レスポンスを実現するPartial Prerenderingのプレビューを共有したいと思います。

Partial Prerenderingは、サーバーサイドレンダリング(SSR)、静的サイト生成(SSG)、およびインクリメンタル静的再検証(ISR)における10年間の研究開発の成果に基づいています。

動機

皆様からのフィードバックをいただきました。現在、考慮すべきランタイム、構成オプション、レンダリング方法が多すぎます。静的サイトの速度と信頼性を望みながら、完全に動的でパーソナライズされたレスポンスもサポートしたいと考えています。

グローバルな優れたパフォーマンスとパーソナライゼーションを、複雑さの代償なしに実現することは、私たちの課題でした。

私たちの課題は、開発者が学習する新しいAPIを導入することなく、既存のモデルを簡素化し、より良い開発者エクスペリエンスを作成することでした。サーバーサイドコンテンツの部分的なキャッシュは存在しますが、これらのアプローチは、私たちが目指す開発者エクスペリエンスとコンポーザビリティの目標を満たす必要があります。

Partial Prerenderingでは、学習する新しいAPIは必要ありません。

React Suspense上に構築

Partial Prerenderingは、Suspense境界によって定義されます。仕組みは次のとおりです。次のeコマースページを検討してください。

app/page.tsx
export default function Page() {
  return (
    <main>
      <header>
        <h1>My Store</h1>
        <Suspense fallback={<CartSkeleton />}>
          <ShoppingCart />
        </Suspense>
      </header>
      <Banner />
      <Suspense fallback={<ProductListSkeleton />}>
        <Recommendations />
      </Suspense>
      <NewProducts />
    </main>
  );
}

Partial Prerenderingが有効になると、このページは<Suspense />境界に基づいて静的なシェルを生成します。React Suspenseのfallbackが事前レンダリングされます。

次に、シェル内のSuspenseフォールバックは、Cookieを読み取ってカートを判断したり、ユーザーに基づいてバナーを表示したりする動的コンポーネントに置き換えられます。

リクエストが発生すると、静的HTMLシェルがすぐに提供されます。

<main>
  <header>
    <h1>My Store</h1>
    <div class="cart-skeleton">
      <!-- Hole -->
    </div>
  </header>
  <div class="banner" />
  <div class="product-list-skeleton">
    <!-- Hole -->
  </div>
  <section class="new-products" />
</main>

<ShoppingCart />cookiesからユーザーセッションを読み取るため、このコンポーネントは静的シェルと同じHTTPリクエストの一部としてストリーミングされます。追加のネットワークラウンドトリップは不要です。

app/cart.tsx
import { cookies } from 'next/headers'
 
export default function ShoppingCart() {
  const cookieStore = cookies()
  const session = cookieStore.get('session')
  return ...
}

最も粒度の細かい静的シェルを作成するには、追加のSuspense境界を追加する必要がある場合があります。ただし、現在loading.jsを使用している場合、これは暗黙的なSuspense境界であるため、静的シェルの生成に何も変更は必要ありません。

近日公開

Partial Prerenderingは活発に開発中です。近日公開されるマイナーリリースで、さらに詳しいアップデートを共有します。

メタデータ改善

ページコンテンツがサーバーからストリーミングされる前に、ビューポート、カラーシェーマ、テーマに関する重要なメタデータがブラウザに送信される必要があります。

これらのmetaタグが初期ページコンテンツとともに送信されるようにすることで、スムーズなユーザーエクスペリエンスが保証され、テーマカラーの変更やビューポートの変更によるレイアウトのシフトによるページのかすつきを防ぎます。

Next.js 14では、ブロックメタデータと非ブロックメタデータを分離しました。メタデータのオプションのごく一部のみがブロックされ、非ブロックメタデータは部分的に事前レンダリングされたページが静的シェルを提供することを妨げないようにします。

次のメタデータオプションは非推奨となり、将来のメジャーバージョンでmetadataから削除されます。

  • viewport: ビューポートの初期ズームやその他のプロパティを設定します。
  • colorScheme: ビューポートのサポートモード(ライト/ダーク)を設定します。
  • themeColor: ビューポートの周りのクロムがレンダリングされる色を設定します。

Next.js 14以降、これらのオプションに代わる新しいオプションとしてviewportgenerateViewportがあります。その他のmetadataオプションはそのままです。

これらの新しいAPIは今日から採用できます。既存のmetadataオプションは引き続き機能します。

Next.js Learnコース

本日、Next.js Learnで、まったく新しい無料コースをリリースします。このコースでは、以下を学びます。

  • Next.js App Router
  • スタイリングとTailwind CSS
  • フォントと画像の最適化
  • レイアウトとページの作成
  • ページ間のナビゲーション
  • Postgresデータベースの設定
  • Server Componentsでのデータ取得
  • 静的および動的レンダリング
  • ストリーミング
  • Partial Prerendering (オプション)
  • 検索とページネーションの追加
  • データの変更
  • エラー処理
  • アクセシビリティの向上
  • 認証の追加
  • メタデータの追加

Next.js Learnは、数百万人の開発者にフレームワークの基礎を教えてきました。新しいコースへのフィードバックをお待ちしています。コースを受講するには、nextjs.org/learnにアクセスしてください。

その他の変更点

  • [Breaking]最小Node.jsバージョンは18.17になりました
  • [Breaking]next-swcビルドのWASMターゲットを削除しました(PR
  • [Breaking]@next/fontのサポートを、next/fontに置き換えて削除しました(Codemod
  • [Breaking]ImageResponseのインポートをnext/serverからnext/ogに変更しました(Codemod
  • [Breaking]next exportコマンドは、output: 'export'設定に置き換えられました(ドキュメント
  • [Deprecation]next/imageonLoadingCompleteは、onLoadに置き換えられます。
  • [Deprecation]next/imagedomainsは、remotePatternsに置き換えられます。
  • [Feature]fetchキャッシングに関するより詳細なロギングを有効にできます(ドキュメント
  • [Improvement]基本的なcreate-next-appアプリケーションの関数サイズが80%削減されました。
  • [Improvement]開発中にedgeランタイムを使用する際のメモリ管理が強化されました。

コントリビューター

Next.jsは、2,900人以上の個々の開発者、GoogleやMetaなどの業界パートナー、およびVercelのコアチームの共同作業の成果です。コミュニティに参加するには、GitHub DiscussionsReddit、およびDiscordへどうぞ。

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

および、@05lazy、@0xadada、@2-NOW、@aarnadlr、@aaronbrown-vercel、@aaronjy、@abayomi185、@abe1272001、@abhiyandhakal、@abstractvector、@acdlite、@adamjmcgrath、@AdamKatzDev、@adamrhunter、@ademilter、@adictonator、@adilansari、@adtc、@afonsojramos、@agadzik、@agrattan0820、@akd-io、@AkifumiSato、@akshaynox、@alainkaiser、@alantoa、@albertothedev、@AldeonMoriak、@aleksa-codes、@alexanderbluhm、@alexkirsz、@alfred-mountfield、@alpha-xek、@andarist、@Andarist、@andrii-bodnar、@andykenward、@angel1254mc、@anonrig、@anthonyshew、@AntoineBourin、@anujssstw、@apeltop、@aralroca、@aretrace、@artdevgame、@artechventure、@arturbien、@Aryan9592、@AviAvinav、@aziyatali、@BaffinLee、@Banbarashik、@bencmbrook、@benjie、@bennettdams、@bertho-zero、@bigyanse、@Bitbbot、@blue-devil1134、@bot08、@bottxiang、@Bowens20832、@bre30kra69cs、@BrennanColberg、@brkalow、@BrodaNoel、@Brooooooklyn、@brunoeduardodev、@brvnonascimento、@carlos-menezes、@cassidoo、@cattmote、@cesarkohl、@chanceaclark、@charkour、@charlesbdudley、@chibicode、@chrisipanaque、@ChristianIvicevic、@chriswdmr、@chunsch、@ciruz、@cjmling、@clive-h-townsend、@colinhacks、@colinking、@coreyleelarson、@Cow258、@cprussin、@craigwheeler、@cramforce、@cravend、@cristobaldominguez95、@ctjlewis、@cvolant、@cxa、@danger-ahead、@daniel-web-developer、@danmindru、@dante-robinson、@darshanjain-entrepreneur、@darshkpatel、@davecarlson、@David0z、@davidnx、@dciug、@delbaoliveira、@denchance、@DerTimonius、@devagrawal09、@DevEsteves、@devjiwonchoi、@devknoll、@DevLab2425、@devvspaces、@didemkkaslan、@dijonmusters、@dirheimerb、@djreillo、@dlehmhus、@doinki、@dpnolte、@Drblessing、@dtinth、@ducanhgh、@DuCanhGH、@ductnn、@duncanogle、@dunklesToast、@DustinsCode、@dvakatsiienko、@dvoytenko、@dylanjha、@ecklf、@EndangeredMassa、@eps1lon、@ericfennis、@escwxyz、@Ethan-Arrowood、@ethanmick、@ethomson、@fantaasm、@feikerwu、@ferdingler、@FernandVEYRIER、@feugy、@fgiuliani、@fomichroman、@Fonger、@ForsakenHarmony、@franktronics、@FSaldanha、@fsansalvadore、@furkanmavili、@g12i、@gabschne、@gaojude、@gdborton、@gergelyke、@gfgabrielfranca、@gidgudgod、@Gladowar、@Gnadhi、@gnoff、@goguda、@greatSumini、@gruz0、@Guilleo03、@gustavostz、@hanneslund、@HarshaVardhanReddyDuvvuru、@haschikeks、@Heidar-An、@heyitsuzair、@hiddenest、@hiro0218、@hotters、@hsrvms、@hu0p、@hughlilly、@HurSungYun、@hustLer2k、@iamarpitpatidar、@ianldgs、@ianmacartney、@iaurg、@ibash、@ibrahemid、@idoob、@iiegor、@ikryvorotenko、@imranbarbhuiya、@ingovals、@inokawa、@insik-han、@isaackatayev、@ishaqibrahimbot、@ismaelrumzan、@itsmingjie、@ivanhofer、@IvanKiral、@jacobsfletch、@jakemstar、@jamespearson、@JanCizmar、@janicklas-ralph、@jankaifer、@JanKaifer、@jantimon、@jaredpalmer、@javivelasco、@jayair、@jaykch、@Jeffrey-Zutt、@jenewland1999、@jeremydouglas、@JesseKoldewijn、@jessewarren-aa、@jimcresswell、@jiwooIncludeJeong、@jocarrd、@joefreeman、@JohnAdib、@JohnAlbin、@JohnDaly、@johnnyomair、@johnta0、@joliss、@jomeswang、@joostdecock、@Josehower、@josephcsoti、@josh、@joshuabaker、@JoshuaKGoldberg、@joshuaslate、@joulev、@jsteele-stripe、@JTaylor0196、@JuanM04、@jueungrace、@juliusmarminge、@Juneezee、@Just-Moh-it、@juzhiyuan、@jyunhanlin、@kaguya3222、@karlhorky、@kevinmitch14、@keyz、@kijikunnn、@kikobeats、@Kikobeats、@kleintorres、@koba04、@koenpunt、@koltong、@konomae、@kosai106、@krmeda、@kvnang、@kwonoj、@ky1ejs、@kylemcd、@labyrinthitis、@lachlanjc、@lacymorrow、@laityned、@Lantianyou、@leerob、@leodr、@leoortizz、@li-jia-nan、@loettz、@lorenzobloedow、@lubakravche、@lucasassisrosa、@lucasconstantino、@lucgagan、@LukeSchlangen、@LuudJanssen、@lycuid、@M3kH、@m7yue、@manovotny、@maranomynet、@marcus-rise、@MarDi66、@MarkAtOmniux、@martin-wahlberg、@masnormen、@matepapp、@matthew-heath、@mattpr、@maxleiter、@MaxLeiter、@maxproske、@meenie、@meesvandongen、@mhmdrioaf、@michaeloliverx、@mike-plummer、@MiLk、@milovangudelj、@Mingyu-Song、@mirismaili、@mkcy3、@mknichel、@mltsy、@mmaaaaz、@mnajdova、@moetazaneta、@mohanraj-r、@molebox、@morganfeeney、@motopods、@mPaella、@mrxbox98、@nabsul、@nathanhammond、@nbouvrette、@nekochantaiwan、@nfinished、@Nick-Mazuk、@nickmccurdy、@niedziolkamichal、@niko20、@nikolovlazar、@nivak-monarch、@nk980113、@nnnnoel、@nocell、@notrab、@nroland013、@nuta、@nutlope、@obusk、@okcoker、@oliviertassinari、@omarhoumz、@opnay、@orionmiz、@ossan-engineer、@patrick91、@pauek、@peraltafederico、@Phiction、@pn-code、@pyjun01、@pythagoras-yamamoto、@qrohlf、@raisedadead、@reconbot、@reshmi-sriram、@reyrodrigez、@ricardofiorani、@rightones、@riqwan、@rishabhpoddar、@rjsdnql123、@rodrigofeijao、@runjuu、@Ryan-Dia、@ryo-manba、@s0h311、@sagarpreet-xflowpay、@sairajchouhan、@samdenty、@samsisle、@sanjaiyan-dev、@saseungmin、@SCG82、@schehata、@Schniz、@sepiropht、@serkanbektas、@sferadev、@ShaunFerris、@shivanshubisht、@shozibabbas、@silvioprog、@simonswiss、@simPod、@sivtu、@SleeplessOne1917、@smaeda-ks、@sonam-serchan、@SonMooSans、@soonoo、@sophiebits、@souporserious、@sp00ls、@sqve、@sreetamdas、@stafyniaksacha、@starunaway、@steebchen、@stefanprobst、@steppefox、@steven-tey、@suhaotian、@sukkaw、@SukkaW、@superbahbi、@SuttonJack、@svarunid、@swaminator、@swarnava、@syedtaqi95、@taep96、@taylorbryant、@teobler、@Terro216、@theevilhead、@thepatrick00、@therealrinku、@thomasballinger、@thorwebdev、@tibi1220、@tim-hanssen、@timeyoutakeit、@tka5、@tknickman、@tomryanx、@trigaten、@tristndev、@tunamagur0、@tvthatsme、@tyhopp、@tyler-lutz、@UnknownMonk、@v1k1、@valentincostam、@valentinh、@valentinpolitov、@vamcs、@vasucp1207、@vicsantizo、@vinaykulk621、@vincenthongzy、@visshaljagtap、@vladikoff、@wherehows、@WhoAmIRUS、@WilderDev、@Willem-Jaap、@williamli、@wiredacorn、@wiscaksono、@wojtekolek、@ws-jm、@wxh06、@wyattfry、@wyattjoh、@xiaolou86、@y-tsubuku、@yagogmaisp、@yangshun、@yasath、@Yash-Singh1、@yigithanyucedag、@ykzts、@Yovach、@yutsuten、@yyuemii、@zek、@zekicaneksi、@zignis、および@zlrlyyの貢献。