2023年10月26日 木曜日
Next.js 14
投稿者Next.js Confで発表した通り、Next.js 14は以下の点を重視したリリースです。
- Turbopack: App RouterとPages Routerで5,000のテストが合格
- ローカルサーバー起動が53%高速化
- Fast Refreshによるコード更新が94%高速化
- Server Actions (安定版): プログレッシブエンハンスメントによるミューテーション
- キャッシュと再検証機能と統合
- シンプルな関数呼び出し、またはフォームとネイティブに連携
- Partial Prerendering (プレビュー): 高速な初期静的応答 + ストリーミング動的コンテンツ
- Next.js Learn (新規): App Router、認証、データベースなどを学べる無料コース。
今すぐアップグレードするか、以下から始めましょう
npx create-next-app@latest
Next.js コンパイラ: ターボチャージ
Next.js 13以降、私たちはPages RouterとApp Routerの両方で、Next.jsのローカル開発パフォーマンスを向上させることに取り組んできました。
以前は、この取り組みをサポートするためにnext dev
やNext.jsの他の部分を書き換えていました。その後、より漸進的なアプローチに変更しました。これは、まずNext.jsのすべての機能をサポートすることに再注力したため、Rustベースのコンパイラが間もなく安定する予定であることを意味します。
私たちの基盤となるRustエンジンであるTurbopackでは、next dev
の5,000の統合テストが現在合格しています。これらのテストには、7年分のバグ修正と再現が含まれています。
大規模なNext.jsアプリケーションであるvercel.com
でテストした結果、以下のことが確認されました。
- ローカルサーバーの起動が最大53.3%高速化
- Fast Refreshによるコード更新が最大94.7%高速化
このベンチマークは、大規模なアプリケーション(および大規模なモジュールグラフ)で期待できるパフォーマンス改善の実用的な結果です。next dev
のテストの90%が現在合格しているため、next dev --turbo
を使用すると、より高速で信頼性の高いパフォーマンスを一貫して得られるはずです。
テストが100%合格すれば、次のマイナーリリースでTurbopackを安定版に移行します。また、カスタム設定やエコシステムプラグインのためにwebpackの使用も引き続きサポートします。
テストの合格率はareweturboyet.comで確認できます。
フォームとミューテーション
Next.js 9ではAPI Routesが導入され、フロントエンドコードと並行してバックエンドのエンドポイントを迅速に構築できるようになりました。
例えば、api/
ディレクトリに新しいファイルを作成します。
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
を行うことができます。
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 (安定版)
API Routeを手動で作成する必要がなければどうでしょうか?代わりに、サーバーで安全に実行され、Reactコンポーネントから直接呼び出される関数を定義することができます。
App RouterはReactのcanary
チャネルをベースにしており、これは新しい機能を採用するフレームワークにとって安定しています。v14以降、Next.jsは最新のReact canary
にアップグレードされ、安定版のServer Actionsが含まれています。
Pages Routerの以前の例は、1つのファイルに簡素化できます。
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といったウェブの基本に基づいています。
フォームを介してServer Actionsを使用することはプログレッシブエンハンスメントに役立ちますが、必須ではありません。フォームなしで、関数として直接呼び出すこともできます。TypeScriptを使用する場合、これによりクライアントとサーバー間の完全なエンドツーエンドの型安全性が提供されます。
データの変更、ページの再レンダリング、またはリダイレクトは1回のネットワークラウンドトリップで発生するため、アップストリームプロバイダが遅い場合でも、クライアントに正しいデータが表示されることが保証されます。さらに、異なるアクションを組み合わせて再利用でき、同じルート内で多くの異なるアクションを含めることも可能です。
キャッシュ、再検証、リダイレクトなど
Server ActionsはApp Routerモデル全体に深く統合されています。以下のことができます。
revalidatePath()
またはrevalidateTag()
でキャッシュされたデータを再検証redirect()
で別のルートへリダイレクトcookies()
でクッキーを設定・読み取りuseOptimistic()
で楽観的UI更新を処理useFormState()
でサーバーからのエラーを捕捉し表示useFormStatus()
でクライアント上のロード状態を表示
Server Actionsを使用したフォームとミューテーション、またはServer ComponentsとServer Actionsのセキュリティモデルとベストプラクティスについて詳しく学ぶことができます。
Partial Prerendering (プレビュー)
Next.jsで現在開発中のPartial Prerendering(高速な初期静的応答と動的コンテンツを組み合わせたコンパイラ最適化)のプレビューを共有したいと思います。
Partial Prerenderingは、サーバーサイドレンダリング(SSR)、静的サイト生成(SSG)、およびインクリメンタル静的再検証(ISR)に関する10年間の研究開発に基づいています。
動機
皆様からのフィードバックを伺いました。現在、考慮すべきランタイム、設定オプション、レンダリングメソッドが多すぎます。静的サイトの速度と信頼性を望みつつ、完全に動的でパーソナライズされた応答もサポートしたいと考えていることでしょう。
グローバルな優れたパフォーマンスとパーソナライゼーションは、複雑さを犠牲にして実現されるべきではありません。
私たちの課題は、開発者が新しいAPIを学ぶ必要なく、既存のモデルを簡素化することで、より良い開発者体験を創出することでした。サーバーサイドコンテンツの部分的なキャッシュは存在していましたが、これらのアプローチは、私たちが目指す開発者体験とコンポーザビリティの目標を満たす必要がありました。
Partial Prerenderingは、新しいAPIを学ぶ必要がありません。
React Suspense上に構築されています
部分的なプリレンダリングは、Suspenseの境界によって定義されます。その仕組みを説明します。以下のeコマースページを考えてみましょう
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>
);
}
部分的なプリレンダリングが有効になっている場合、このページは<Suspense />
の境界に基づいて静的なシェルを生成します。React Suspenseのfallback
がプリレンダリングされます。
シェル内のSuspenseフォールバックは、カートを決定するためにクッキーを読み込んだり、ユーザーに基づいてバナーを表示したりするような動的なコンポーネントに置き換えられます。
リクエストが行われると、静的な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リクエストの一部としてストリーミングされます。追加のネットワークラウンドトリップは不要です。
import { cookies } from 'next/headers'
export default function ShoppingCart() {
const cookieStore = cookies()
const session = cookieStore.get('session')
return ...
}
最もきめ細かい静的シェルを持つためには、追加のSuspense境界が必要になる場合があります。ただし、現在loading.js
を使用している場合は、これは暗黙的なSuspense境界であるため、静的シェルを生成するために変更は必要ありません。
近日公開
部分的なプリレンダリングは現在活発に開発中です。今後のマイナーリリースでさらなるアップデートを共有します。
メタデータ改善
ページコンテンツがサーバーからストリーミングされる前に、ビューポート、カラースキーム、テーマに関する重要なメタデータが最初にブラウザに送信される必要があります。
これらのmeta
タグが最初のページコンテンツとともに送信されるようにすることで、テーマカラーの変更によるページのちらつきや、ビューポートの変更によるレイアウトのずれを防ぎ、スムーズなユーザーエクスペリエンスに貢献します。
Next.js 14では、ブロッキングメタデータと非ブロッキングメタデータを分離しました。メタデータオプションのごく一部のみがブロッキングであり、非ブロッキングメタデータが部分的にプリレンダリングされたページによる静的シェルの提供を妨げないようにしたいと考えています。
以下のメタデータオプションは現在非推奨であり、将来のメジャーバージョンでmetadata
から削除されます
viewport
: ビューポートの初期ズームおよびその他のプロパティを設定しますcolorScheme
: ビューポートのサポートモード(ライト/ダーク)を設定しますthemeColor
: ビューポート周辺のChromeがレンダリングされるべき色を設定します
Next.js 14からは、これらのオプションを置き換える新しいオプションviewport
とgenerateViewport
が導入されます。その他のmetadata
オプションはすべて同じままです。
これらの新しいAPIは本日より導入を開始できます。既存のmetadata
オプションは引き続き動作します。
Next.js Learnコース
本日、Next.js Learnで新しい無料コースを公開します。このコースでは以下を学習します
- Next.js App Router
- スタイリングとTailwind CSS
- フォントと画像の最適化
- レイアウトとページの作成
- ページ間の移動
- Postgresデータベースのセットアップ
- サーバーコンポーネントによるデータフェッチ
- 静的および動的レンダリング
- ストリーミング
- 部分的なプリレンダリング(オプション)
- 検索とページネーションの追加
- データの変更
- エラー処理
- アクセシビリティの改善
- 認証の追加
- メタデータの追加
Next.js Learnは、何百万もの開発者にフレームワークの基礎を教えてきました。この新しい追加機能について、皆様からのフィードバックをお待ちしております。コースを受講するには、nextjs.org/learnにアクセスしてください。
その他の変更点
- [破壊的変更] Node.jsの最小バージョンが
18.17
になりました - [破壊的変更]
next-swc
ビルドのWASMターゲットを削除しました (PR) - [破壊的変更]
@next/font
のサポートを終了し、next/font
を優先するように変更しました (Codemod) - [破壊的変更]
ImageResponse
のインポートをnext/server
からnext/og
に変更しました (Codemod) - [破壊的変更]
next export
コマンドは廃止され、output: 'export'
設定が推奨されます (ドキュメント) - [非推奨]
next/image
のonLoadingComplete
は非推奨となり、onLoad
に置き換えられます。 - [非推奨]
next/image
のdomains
は非推奨となり、remotePatterns
に置き換えられます。 - [機能]
fetch
キャッシュに関するより詳細なログを有効にできるようになりました (ドキュメント) - [改善] 基本的な
create-next-app
アプリケーションの関数サイズが80%削減されました - [改善] 開発時に
edge
ランタイムを使用する際のメモリ管理が強化されました
貢献者
Next.jsは、2,900人以上の個々の開発者、GoogleやMetaのような業界パートナー、そしてVercelのコアチームの共同作業の成果です。GitHub Discussions、Reddit、そしてDiscordでコミュニティに参加してください。
このリリースは、以下のチームの協力によって実現しました。
- Next.jsチーム: Andrew、 Balazs、 Jiachi、 Jimmy、 JJ、 Josh、 Sebastian、 Shu、 Steven、 Tim、 Wyatt、および Zack。
- Turbopackチーム: Donny、 Justin、 Leah、 Maia、 OJ、 Tobias、および Will。
- Next.js Learn: Delba、 Steph、 Emil、 Balazs、 Hector、および Amy。
および、以下の皆様の貢献によるものです: @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, @mrkldshv, @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, and @zlrlyy