2023年10月26日,星期四
Next.js 14
发布者正如我们在 Next.js Conf 上宣布的,Next.js 14 是我们最专注的版本,它带来了
- Turbopack:5,000 个测试用例通过,支持 App Router 和 Pages Router
- 本地服务器启动速度提升 53%
- 使用 Fast Refresh 代码更新速度提升 94%
- 服务器 Actions (稳定版):渐进增强的 mutations
- 与缓存和重新验证集成
- 简单的函数调用,或原生支持表单
- 部分预渲染 (预览版):快速初始静态响应 + 流式传输动态内容
- Next.js Learn (全新):免费课程,教授 App Router、身份验证、数据库等。
立即升级或开始使用
npx create-next-app@latest
Next.js 编译器:性能 Turbocharged
自 Next.js 13 以来,我们一直致力于提升 Next.js 在 Pages Router 和 App Router 中的本地开发性能。
此前,我们为了支持这项工作,正在重写 `next dev` 和 Next.js 的其他部分。之后,我们将方法改为更渐进式。这意味着我们基于 Rust 的编译器将很快达到稳定状态,因为我们已将重点重新放在首先支持所有 Next.js 功能上。
现在,`next dev` 的 5,000 个集成测试用例已通过,这得益于我们的底层 Rust 引擎 Turbopack。这些测试包括 7 年的错误修复和重现。
在 vercel.com 这个大型 Next.js 应用程序上进行测试时,我们看到
- 本地服务器启动速度最高提升 53.3%
- 使用 Fast Refresh 代码更新速度最高提升 94.7%
此基准测试是您在使用大型应用程序(和大型模块图)时应期望看到的性能提升的实际结果。随着 `next dev` 90% 的测试用例现在通过,当使用 `next dev --turbo` 时,您应该会看到更快、更可靠的性能。
一旦我们达到 100% 的测试用例通过率,我们将在即将到来的小版本中将 Turbopack 移至稳定版。我们也将继续支持使用 webpack 进行自定义配置和生态系统插件。
您可以在 areweturboyet.com 上关注测试用例的通过率。
表单和 Mutations
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 中,我们希望简化开发人员编写数据 mutations 的体验。此外,我们希望在用户网络连接缓慢或从低功耗设备提交表单时,改善用户体验。
服务器 Actions (稳定版)
如果您不需要手动创建 API Route 会怎么样?相反,您可以定义一个在服务器上安全运行的函数,直接从您的 React 组件中调用。
App Router 构建于 React `canary` 通道之上,该通道对于 框架采用新功能来说是稳定的。截至 v14,Next.js 已升级到最新的 React `canary`,其中包括稳定的服务器 Actions。
Pages Router 中之前的示例可以简化为一个文件
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>
);
}
对于任何以前使用过以服务器为中心的框架的开发人员来说,服务器 Actions 应该会感到熟悉。它构建于 Web 基础知识之上,例如表单和 FormData Web API。
虽然通过表单使用服务器 Actions 对于渐进增强很有帮助,但这不是必需的。您也可以直接将它们作为函数调用,而无需表单。当使用 TypeScript 时,这为您提供了客户端和服务器之间完整的端到端类型安全。
数据 mutations、重新渲染页面或重定向可以在一次网络往返中完成,即使上游提供程序速度较慢,也能确保在客户端显示正确的数据。此外,您可以组合和重用不同的 actions,包括在同一路由中使用许多不同的 actions。
缓存、重新验证、重定向等
服务器 Actions 深度集成到整个 App Router 模型中。您可以
- 使用
revalidatePath()
或revalidateTag()
重新验证缓存数据 - 通过
redirect()
重定向到不同的路由 - 通过
cookies()
设置和读取 cookies - 使用
useOptimistic()
处理乐观 UI 更新 - 使用
useFormState()
捕获和显示来自服务器的错误 - 使用
useFormStatus()
在客户端显示加载状态
了解更多关于使用服务器 Actions 的表单和 Mutations 的信息,或关于服务器组件和服务器 Actions 的安全模型和最佳实践。
部分预渲染 (预览版)
我们想分享部分预渲染的预览版 —— 这是我们正在为 Next.js 开发的一种编译器优化,它针对动态内容提供快速的初始静态响应。
部分预渲染建立在十年对服务器端渲染 (SSR)、静态站点生成 (SSG) 和增量静态重新验证 (ISR) 的研究和开发之上。
动机
我们听到了您的反馈。目前有太多的运行时、配置选项和渲染方法需要考虑。您希望获得静态的速度和可靠性,同时还支持完全动态的、个性化的响应。
在全球范围内拥有出色的性能和个性化功能不应以复杂性为代价。
我们的挑战是创建更好的开发者体验,简化现有模型,而无需引入新的 API 供开发者学习。虽然服务器端内容的局部缓存已经存在,但这些方法仍然需要满足我们旨在实现的开发者体验和可组合性目标。
部分预渲染不需要学习新的 API。
构建于 React Suspense 之上
部分预渲染由您的 Suspense 边界定义。以下是它的工作原理。考虑以下电子商务页面
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 />
边界生成静态 shell。React Suspense 的 fallback
会被预渲染。
然后,shell 中的 Suspense fallbacks 会被动态组件替换,例如读取 cookies 以确定购物车,或根据用户显示横幅。
当发出请求时,静态 HTML shell 会立即被服务
<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
中读取以查找用户会话,因此该组件会作为与静态 shell 相同的 HTTP 请求的一部分流式传输进来。无需额外的网络往返。
import { cookies } from 'next/headers'
export default function ShoppingCart() {
const cookieStore = cookies()
const session = cookieStore.get('session')
return ...
}
为了获得最精细的静态 shell,这可能需要添加额外的 Suspense 边界。但是,如果您今天已经在使用 loading.js
,这是一个隐式的 Suspense 边界,因此无需进行任何更改即可生成静态 shell。
即将推出
部分预渲染正在积极开发中。我们将在即将到来的小版本中分享更多更新。
元数据改进
在您的页面内容可以从服务器流式传输之前,需要首先将关于视口、配色方案和主题的重要元数据发送到浏览器。
确保这些 meta
标签与初始页面内容一起发送有助于实现流畅的用户体验,防止页面因主题颜色更改而闪烁,或因视口更改而导致布局偏移。
在 Next.js 14 中,我们解耦了阻塞和非阻塞元数据。只有一小部分元数据选项是阻塞的,我们希望确保非阻塞元数据不会阻止部分预渲染页面服务静态 shell。
以下元数据选项现已弃用,并将在未来的主要版本中从 `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 数据库
- 使用服务器组件获取数据
- 静态和动态渲染
- 流式传输
- 部分预渲染(可选)
- 添加搜索和分页
- 数据 Mutations
- 处理错误
- 提升可访问性
- 添加身份验证
- 添加元数据
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'
配置 (Docs) - [已弃用]
next/image
的onLoadingComplete
已弃用,转而支持onLoad
- [已弃用]
next/image
的domains
已弃用,转而支持remotePatterns
- [新特性] 可以启用关于
fetch
缓存的更详细的日志记录 (Docs) - [改进] 基本
create-next-app
应用程序的函数大小缩小 80% - [改进] 在开发中使用
edge
运行时时,增强了内存管理
贡献者
Next.js 是超过 2,900 位个人开发者、谷歌和 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, 和 @zlrlyy