2024年1月18日,星期四
Next.js 14.1
发布者Next.js 14.1 包含了开发者体验改进,包括
- 改进的自托管: 新的文档和自定义缓存处理器
- Turbopack改进:
next dev --turbo
通过了 5600 个测试 - 开发者体验改进: 改进的错误消息,
pushState
和replaceState
支持 - 并行和拦截路由: 基于您的反馈修复了 20 个错误
next/image
改进:<picture>
、艺术指导和暗模式支持
立即升级或开始使用
npx create-next-app@latest
改进的自托管
我们听到了您关于如何使用 Node.js 服务器、Docker 容器或静态导出自托管 Next.js 的改进清晰度的反馈。我们已经彻底修改了我们关于自托管的文档
使用 Next.js 14.1,我们还稳定了为增量静态再生和应用路由的更细粒度的 Data Cache 提供自定义缓存处理程序
module.exports = {
cacheHandler: require.resolve('./cache-handler.js'),
cacheMaxMemorySize: 0, // disable default in-memory caching
};
在自托管时使用此配置非常重要,尤其是在使用 Kubernetes 等容器编排平台时,因为每个 Pod 都会拥有缓存的副本。使用自定义缓存处理器将允许您确保托管 Next.js 应用程序的所有 Pod 之间的一致性。
例如,您可以将缓存的值保存到任何地方,例如 Redis 或 Memcached。我们要感谢 @neshca
提供的 Redis 缓存处理器适配器 和示例。
Turbopack 改进
我们继续专注于本地 Next.js 开发的可靠性和性能
- 可靠性:Turbopack 通过了整个 Next.js 开发测试套件,并用于 Vercel 的应用程序
- 性能:改进 Turbopack 的初始编译时间和快速刷新时间
- 内存使用:改进 Turbopack 的内存使用
我们计划在即将发布的版本中稳定 next dev --turbo
,它仍然是可选的。
可靠性
使用 Turbopack 的 Next.js 现在通过了 **5600 个开发测试(94%)**,比上次更新增加了 600 个。您可以在 areweturboyet.com 上跟踪进度。
我们继续在所有 Vercel 的 Next.js 应用程序上使用 next dev --turbo
,包括 vercel.com 和 v0.dev。所有从事这些应用程序开发的工程师每天都在使用 Turbopack。
我们发现并修复了使用 Turbopack 的非常大的 Next.js 应用程序的一些问题。为了解决这些问题,我们在 Next.js 中现有的开发测试套件中添加了新的测试。
性能
对于大型 Next.js 应用程序 vercel.com,我们看到了
- 本地服务器启动速度提高了 **76.7%**
- 使用快速刷新更新代码的速度提高了 **96.3%**
- 初始路由编译(不带缓存)速度提高了 **45.8%**(Turbopack 尚未实现磁盘缓存)
在 v0.dev 中,我们发现了一个优化 Turbopack 中发现和捆绑 React 客户端组件方式的机会,从而使初始编译时间 **最多提高了 61.5%**。在 vercel.com 中也观察到了这种性能改进。
未来的改进
Turbopack 目前具有内存缓存,可以提高快速刷新的增量编译时间。
但是,在重新启动 Next.js 开发服务器时,缓存当前不会保留。Turbopack 性能的下一个重要步骤是 **磁盘缓存**,这将允许在重新启动开发服务器时保留缓存。
开发者体验改进
改进的错误消息和快速刷新
我们知道清晰的错误信息对于您的本地开发体验至关重要。我们在运行next dev
时,对改进堆栈跟踪和错误消息的质量进行了一些修复。
- 以前显示捆绑程序错误(如
webpack-internal
)的错误现在会正确显示错误的源代码和受影响的文件。 - 在客户端组件中看到错误并在编辑器中修复错误后,快速刷新功能不会清除错误屏幕,需要硬刷新才能解决。我们已经修复了许多此类问题。例如,尝试从客户端组件导出
metadata
。
例如,这是一个之前的错误信息
Next.js 14.1 已将其改进为
window.history.pushState
和 window.history.replaceState
App Router 现在允许使用原生pushState
和 replaceState
方法来更新浏览器的历史记录栈,而无需重新加载页面。
pushState
和 replaceState
调用集成到 Next.js App Router 中,允许您与usePathname
和 useSearchParams
同步。
这在需要在保存状态(如筛选器、排序顺序或其他希望在重新加载时保留的信息)时立即更新 URL 时非常有用。
'use client';
import { useSearchParams } from 'next/navigation';
export default function SortProducts() {
const searchParams = useSearchParams();
function updateSorting(sortOrder: string) {
const params = new URLSearchParams(searchParams.toString());
params.set('sort', sortOrder);
window.history.pushState(null, '', `?${params.toString()}`);
}
return (
<>
<button onClick={() => updateSorting('asc')}>Sort Ascending</button>
<button onClick={() => updateSorting('desc')}>Sort Descending</button>
</>
);
}
详细了解如何将原生 History API 与 Next.js 配合使用。
数据缓存日志
为了提高在运行next dev
时 Next.js 应用程序中缓存数据的可观察性,我们对logging
配置选项进行了一些改进。
您现在可以显示是否存在缓存HIT
或 SKIP
以及请求的完整 URL。
GET / 200 in 48ms
✓ Compiled /fetch-cache in 117ms
GET /fetch-cache 200 in 165ms
│ GET https://api.vercel.app/products/1 200 in 14ms (cache: HIT)
✓ Compiled /fetch-no-store in 150ms
GET /fetch-no-store 200 in 548ms
│ GET https://api.vercel.app/products/1 200 in 345ms (cache: SKIP)
│ │ Cache missed reason: (cache: no-store)
可以通过next.config.js
启用此功能。
module.exports = {
logging: {
fetches: {
fullUrl: true,
},
},
};
next/image
支持<picture>
和艺术指导
Next.js Image 组件现在通过getImageProps()
(稳定版)支持更高级的用例,这些用例不需要直接使用<Image>
。这包括
- 使用
background-image
或image-set
- 使用 canvas
context.drawImage()
或new Image()
- 使用
<picture>
媒体查询来实现艺术指导 或亮/暗模式图像
import { getImageProps } from 'next/image';
export default function Page() {
const common = { alt: 'Hero', width: 800, height: 400 };
const {
props: { srcSet: dark },
} = getImageProps({ ...common, src: '/dark.png' });
const {
props: { srcSet: light, ...rest },
} = getImageProps({ ...common, src: '/light.png' });
return (
<picture>
<source media="(prefers-color-scheme: dark)" srcSet={dark} />
<source media="(prefers-color-scheme: light)" srcSet={light} />
<img {...rest} />
</picture>
);
}
详细了解getImageProps()
。
并行和拦截路由
在 Next.js 14.1 中,我们对并行和拦截路由进行了**20 项改进**。
在过去的两个版本中,我们一直专注于提高 Next.js 的性能和可靠性。现在,我们已经能够根据您的反馈对并行 和 拦截路由 进行许多改进。值得注意的是,我们添加了对通配符路由和服务器操作的支持。
- 并行路由允许您在同一布局中同时或有条件地渲染一个或多个页面。对于应用程序中高度动态的部分(例如社交网站上的仪表板和 Feed),并行路由可用于实现复杂的路由模式。
- 拦截路由允许您从应用程序的另一个部分加载路由到当前布局中。例如,当您在 Feed 中点击照片时,您可以将照片显示在模态窗口中,覆盖 Feed。在这种情况下,Next.js 会拦截
/photo/123
路由,屏蔽 URL,并将其覆盖在/feed
上。
其他改进
从14.0
开始,我们修复了许多社区中获得高度评价的错误。
我们最近还发布了一些视频,解释缓存,以及一些App Router 的常见错误,您可能会觉得这些视频很有帮助。
- [文档] 关于重定向 的新文档
- [文档] 关于测试 的新文档
- [文档] 包含生产检查清单 的新文档
- [特性] 将
<GoogleAnalytics />
组件添加到next/third-parties
中(文档) - [改进]
create-next-app
现在更小,安装速度更快(PR) - [改进] 嵌套路由抛出的错误现在可以被
global-error
捕获(PR) - [改进]
redirect
现在在服务器操作中尊重basePath
(PR) - [改进] 修复了 App Router 中
next/script
和beforeInteractive
的使用问题(PR) - [改进] 自动转译
@aws-sdk
和lodash
以加快路由启动速度(PR) - [改进] 修复了使用
next dev
和next/font
时出现的未样式内容闪烁问题(PR) - [改进] 将
notFound
错误传播到段错误边界之外(PR) - [改进] 修复了使用 Pages Router 国际化时从区域设置域名提供公共文件的问题(PR)
- [改进] 如果传递了无效的
revalidate
值,则会报错(PR) - [改进] 修复了在 Linux 机器上构建在 Windows 上创建的构建时出现的路径问题(PR)
- [改进] 修复了在使用多区域应用和
basePath
时快速刷新/HMR 的问题(PR) - [改进] 改进了从终止信号优雅关闭的过程(PR)
- [改进] 修复了模式路由在从不同路由拦截时发生的冲突问题(PR)
- [改进] 修复了在使用
basePath
配置时拦截路由的问题(PR) - [改进] 当缺少的并行插槽导致 404 时显示警告(PR)
- [改进] 改进了在与通配符路由一起使用时拦截路由的方式(PR)
- [改进] 改进了在与
revalidatePath
一起使用时拦截路由的方式(PR) - [改进] 修复了在并行路由中使用
@children
插槽的问题(PR) - [改进] 修复了在并行路由中使用参数时出现的 TypeError 错误(PR)
- [改进] 修复了默认并行路由的通配符路由规范化问题(PR)
- [改进] 修复了
next build
摘要中并行路由的显示问题(PR) - [改进] 修复了在使用拦截路由时的路由参数问题(PR)
- [改进] 改进了深度嵌套的并行/拦截路由(PR)
- [改进] 修复了拦截路由与路由组配对时出现的 404 问题(PR)
- [改进] 修复了并行路由与服务器操作/重新验证路由缓存的问题(PR)
- [改进] 修复了在拦截路由中使用
rewrites
的问题(PR) - [改进] 服务器操作现在可以从第三方库中工作(PR)
- [改进] Next.js 现在可以用于 ESM 包中(PR)
- [改进] 针对 Material UI 等库的 Barrel 文件优化 (PR)
- [改进] 构建过程现在会在不使用
Suspense
的情况下错误使用useSearchParams
时失败 (PR)
贡献者
Next.js 是超过 3000 位独立开发者、Google 和 Meta 等行业合作伙伴以及 Vercel 核心团队共同努力的成果。加入社区,参与 GitHub 讨论、Reddit 和 Discord。
此版本由以下人员贡献
- Next.js 团队:Andrew、Balazs、贾驰、Jimmy、JJ、Josh、Sebastian、Shu、Steven、Tim、Wyatt 和 Zack。
- Turbopack 团队:Donny、Leah、Maia、OJ、Tobias 和 Will。
- Next.js 文档:Delba、Steph、Michael 和 Lee。
以及以下人员的贡献:@OlehDutchenko、@eps1lon、@ebidel、@janicklas-ralph、@JohnPhamous、@chentsulin、@akawalsky、@BlankParticle、@dvoytenko、@smaeda-ks、@kenji-webdev、@rv-david、@icyJoseph、@dijonmusters、@A7med3bdulBaset、@jenewland1999、@mknichel、@kdy1、@housseindjirdeh、@max-programming、@redbmk、@SSakibHossain10、@jamesmillerburgess、@minaelee、@officialrajdeepsingh、@LorisSigrist、@yesl-kim、@StevenKamwaza、@manovotny、@mcexit、@remcohaszing、@ryo-manba、@TranquilMarmot、@vinaykulk621、@haritssr、@divquan、@IgorVaryvoda、@LukeSchlangen、@RiskyMH、@ash2048、@ManuWeb3、@msgadi、@dhayab、@ShahriarKh、@jvandenaardweg、@DestroyerXyz、@SwitchBladeAK、@ianmacartney、@justinh00k、@tiborsaas、@ArianHamdi、@li-jia-nan、@aramikuto、@jquinc30、@samcx、@Haosik、@AkifumiSato、@arnabsen、@nfroidure、@clbn、@siddtheone、@zbauman3、@anthonyshew、@alexfradiani、@CalebBarnes、@adk96r、@pacexy、@hichemfantar、@michaldudak、@redonkulus、@k-taro56、@mhughdo、@tknickman、@shumakmanohar、@vordgi、@hamirmahal、@gaspar09、@JCharante、@sjoerdvanBommel、@mass2527、@N-Ziermann、@tordans、@davidthorand、@rmathew8-gh、@chriskrogh、@shogunsea、@auipga、@SukkaW、@agustints、@OXXD、@clarencepenz、@better-salmon、@808vita、@coltonehrman、@tksst、@hugo-syn、@JakobJingleheimer、@Willem-Jaap、@brandonnorsworthy、@jaehunn、@jridgewell、@gtjamesa、@mugi-uno、@kentobento、@vivianyentran、@empflow、@samennis1、@mkcy3、@suhaotian、@imevanc、@d3lm、@amannn、@hallatore、@Dylan700、@mpsq、@mdio、@christianvuerings、@karlhorky、@simonhaenisch、@olci34、@zce、@LavaToaster、@rishabhpoddar、@jirihofman、@codercor、@devjiwonchoi、@JackieLi565、@thoushif、@pkellner、@jpfifer、@quisido、@tomfa、@raphaelbadia、@j9141997、@hongaar、@MadCcc、@luismulinari、@dumb-programmer、@nonoakij、@franky47、@robbertstevens、@bryndyment、@marcosmartini、@functino、@Anisi、@AdonisAgelis、@seangray-dev、@prkagrawal、@heloineto、@kn327、@ihommani、@MrNiceRicee、@falsepopsky、@thomasballinger、@tmilewski、@Vadman97、@dnhn、@RodrigoTomeES、@sadikkuzu、@gffuma、@Schniz、@joulev、@Athrun-Judah、@rasvanjaya21、@rashidul0405、@nguyenbry、@Mwimwii、@molebox、@mrr11k、@philwolstenholme、@IgorKowalczyk、@Zoe-Bot、@HanCiHu、@JackHowa、@goncy、@hirotomoyamada、@pveyes、@yeskunall、@ChendayUP、@hmaesta、@ajz003、@its-kunal、@joelhooks、@blurrah、@tariknh、@Vinlock、@Nayeem-XTREME、@aziyatali、@aspehler 和 @moka-ayumu。