距 Next.js 14 发布到现在将近 3 个月,Next.js 14.1 现在来了,本次包含了一些开发者体验的改进,主要内容如下:
- 改进的自托管: 新文档和自定义缓存处理程序
- Turbopack 改进: 对于
next dev --turbo的 5600 个测试通过 - 开发者体验改进: 完善了错误消息、
pushState和replaceState支持 - 并行与拦截路由: 基于用户的反馈进行了 20 个改进
- next/image 改进: 支持
<picture>, art direction(艺术方向)和暗模式
改进的自托管
针对如何使用 Node.js 服务器、Docker 容器或静态导出进行自托管,我们更新了文档,提供了更清晰的指南。我们在以下方面改进了自托管文档:
- 运行时环境变量[1]
- ISR 的自定义缓存配置[2]
- 自定义图像优化[3]
- 中间件[4]
在 Next.js 14.1 中,我们还稳定了为增量静态再生提供自定义缓存处理程序以及用于 App Router 的更细粒度的数据缓存:
module.exports = {
cacheHandler: require.resolve('./cache-handler.js'),
cacheMaxMemorySize: 0, // 禁用默认的内存缓存
};
在使用容器编排平台(如 Kubernetes)进行自托管时,使用自定义缓存处理程序对于确保所有托管 Next.js 应用程序的 Pod 之间的一致性非常重要。例如,您可以将缓存的值保存在 Redis 或 Memcached 等地方。我们要感谢 @neshca 提供的 Redis 缓存处理程序适配器[5]和示例。
Turbopack 改进
我们持续关注本地 Next.js 开发的可靠性和性能:
- 可靠性:Turbopack 通过整个 Next.js 开发测试套件,并在 Vercel 的应用中使用
- 性能:改进 Turbopack 的初始编译时间和快速刷新时间
- 内存使用:改进 Turbopack 的内存使用
可靠性
Turbopack 现在通过 5,600 个开发测试(94%)(比上次更新多 600 个)。您可以在 areweturboyet.com[6] 上追踪进展。
我们一直在所有 Vercel 的 Next.js 应用程序上使用 next dev --turbo 进行自测,包括 vercel.com 和 v0.dev。所有在这些应用程序上工作的工程师每天都在使用 Turbopack。
我们在使用 Turbopack 的大型 Next.js 应用程序中发现并修复了一些问题。对于这些修复,我们已经在现有的 Next.js 开发测试套件中添加了新的测试。
性能:
对于 vercel.com(一个大型 Next.js 应用程序)我们观察到:
- 本地服务器启动速度最多提高了 76.7%
- 使用 Fast Refresh 进行代码更新的速度最多提高了 96.3%
- 不使用缓存的初始路由编译速度最多提高了 45.8%(Turbopack 尚未支持磁盘缓存)
在 v0.dev 中,我们发现优化 React 客户端组件在 Turbopack 中的 discovered(发现)和打包方式,初始编译时间最多提高了 61.5%。这种性能改进也在 vercel.com 中观察到。
未来改进:
Turbopack 目前使用内存缓存,以提高 Fast Refresh 的增量编译时间。然而,当重新启动 Next.js 开发服务器时,缓存目前不会被保留。Turbopack 性能的下一个重要步骤是磁盘缓存,这将允许在重新启动开发服务器时保留缓存。
开发者体验改进:
改进的错误消息和 Fast Refresh:
我们知道清晰的错误消息对于您的本地开发体验至关重要。我们进行了一些修复,以提高在运行 next dev 时看到的堆栈跟踪和错误消息的质量。
- 之前显示捆绑器错误(如
webpack-internal)的错误现在会正确显示错误的源代码和受影响的文件。 - 在查看客户端组件中的错误后,在编辑器中修复错误后,Fast Refresh 没有清除错误屏幕。这需要进行硬刷新。我们已经修复了许多这类情况,例如尝试从客户端组件导出元数据。
例如,这是之前 “Next.js 14 中从 fetch 调用产生的错误的一个示例” 的错误消息:
Next.js 14 中从 fetch 调用产生的错误的一个示例
Next.js 14.1 已经改进为:
渲染期间发生的 fetch 调用错误现在会显示错误的源代码和受影响的文件。
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>
</>
);
}
了解有关在 Next.js 中使用 原生 History API[7] 的更多信息。
数据缓存日志:
为了在运行 next dev 时改进在 Next.js 应用程序中缓存数据的可观察性,我们对日志记录配置选项进行了一些改进。
现在,您可以显示是否存在缓存命中(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>媒体查询一起工作,实现艺术方向或 Light/Dark 暗黑模式图像
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()[8]
并行与拦截路由:
在 Next.js 14.1 中,我们对并行与拦截路由进行了 20 次改进。
在过去的两个版本中,我们一直致力于改善 Next.js 的性能和可靠性。现在,根据您的反馈,我们已经在并行与拦截路由上进行了许多改进。值得注意的是,我们添加了对全局捕获路由和 Server Actions 的支持。
- 并行路由:允许您同时或有条件地在相同的布局中渲染一个或多个页面。对于应用程序的高度动态部分,例如社交网站上的 Dashboard 和 Feeds(动态消息),可以使用并行路由来实现复杂的路由模式。
- 拦截路由:允许您在当前布局中从应用程序的另一部分加载路由。例如,在动态消息中点击照片时,您可以在 Modal 中显示照片,覆盖在动态消息上。在这种情况下,Next.js 拦截
/photo/123路由,掩盖 URL,并将其叠加在/feed上。
了解更多关于并行与拦截路由的信息或查看一个示例[9]。
其他改进:
自从 14.0 版本以来,我们已经修复了社区中一些得到高投票的 bug。
我们最近还发布了一些解释缓存[10]和一些可能对您有帮助的 App Router 常见错误[11]的视频。
本文翻译自 Next.js 官方博客 nextjs.org/blog/next-1…