2024年10月21日,星期一
Next.js 15
发布者Next.js 15 正式稳定并准备投入生产。此版本基于 RC1 和 RC2 的更新构建。我们专注于稳定性,同时添加了一些我们认为您会喜欢的令人兴奋的更新。立即尝试 Next.js 15
# Use the new automated upgrade CLI
npx @next/codemod@canary upgrade latest
# ...or upgrade manually
npm install next@latest react@rc react-dom@rc
我们也激动地分享更多关于接下来将会发生什么的信息,在Next.js Conf,本周四,10月24日。
以下是 Next.js 15 中的新功能
@next/codemod
CLI:轻松升级到最新的 Next.js 和 React 版本。- 异步请求 API(重大变更):朝着简化的渲染和缓存模型迈出的增量步骤。
- 缓存语义(重大变更):
fetch
请求、GET
路由处理程序和客户端导航默认不再缓存。 - React 19 支持:支持 React 19、React 编译器(实验性)和水合错误改进。
- Turbopack 开发版(稳定版):性能和稳定性改进。
- 静态路由指示器:新的视觉指示器在开发过程中显示静态路由。
unstable_after
API(实验性):在响应完成流式传输后执行代码。instrumentation.js
API(稳定版):用于服务器生命周期可观察性的新 API。- 增强表单 (
next/form
):通过客户端导航增强 HTML 表单。 next.config
:next.config.ts
的 TypeScript 支持。- 自托管改进:更好地控制
Cache-Control
标头。 - 服务器操作安全性:不可猜测的端点和删除未使用的操作。
- 捆绑外部包(稳定版):App 和 Pages 路由器的新配置选项。
- ESLint 9 支持:添加了对 ESLint 9 的支持。
- 开发和构建性能:改进构建时间和更快的快速刷新。
使用 @next/codemod
CLI 实现平滑升级
我们在每次 Next.js 主要版本发布时都包含代码修改(自动代码转换),以帮助自动化升级重大更改。
为了使升级更加顺畅,我们发布了增强版的代码修改 CLI
npx @next/codemod@canary upgrade latest
此工具可帮助您将代码库升级到最新的稳定版或预发布版。CLI 将更新您的依赖项,显示可用的代码修改,并指导您完成应用它们的过程。
canary
标签使用代码修改的最新版本,而 latest 指定 Next.js 版本。我们建议使用代码修改的 canary 版本,即使您要升级到最新的 Next.js 版本,因为我们计划根据您的反馈继续改进此工具。
详细了解 Next.js 代码修改 CLI。
异步请求 API(重大变更)
在传统的服务器端渲染中,服务器在渲染任何内容之前会等待请求。但是,并非所有组件都依赖于特定于请求的数据,因此无需等待请求来渲染它们。理想情况下,服务器会在请求到达之前尽可能多地准备内容。为了实现这一点,并为未来的优化做好准备,我们需要知道何时等待请求。
因此,我们正在将依赖于特定于请求的数据(例如 headers
、cookies
、params
和 searchParams
)的 API 转换为异步。
import { cookies } from 'next/headers';
export async function AdminPanel() {
const cookieStore = await cookies();
const token = cookieStore.get('token');
// ...
}
这是一个重大变更,会影响以下 API
cookies
headers
draftMode
layout.js
、page.js
、route.js
、default.js
、generateMetadata
和generateViewport
中的params
page.js
中的searchParams
为了更轻松地迁移,这些 API 可以暂时以同步方式访问,但在开发和生产环境中会显示警告,直到下一个主要版本。一个 代码修改 可用于自动执行迁移
npx @next/codemod@canary next-async-request-api .
对于代码修改无法完全迁移代码的情况,请阅读 升级指南。我们还提供了一个 示例 说明如何将 Next.js 应用程序迁移到新的 API。
缓存语义
Next.js App 路由器启动时具有明确的缓存默认值。这些旨在默认提供性能最佳的选项,并在需要时能够选择退出。
根据您的反馈,我们重新评估了我们的 缓存启发式方法 以及它们将如何与部分预渲染 (PPR) 和使用 fetch
的第三方库交互。
在 Next.js 15 中,我们正在更改 fetch
请求、GET
路由处理程序和客户端路由器缓存的缓存默认值,从默认缓存更改为默认不缓存。如果您想保留之前的行为,可以继续选择加入缓存。
我们将在未来几个月继续改进 Next.js 中的缓存,我们很快就会分享更多详细信息。
fetch
请求不再默认缓存
Next.js 使用 Web fetch
API 的缓存选项来配置服务器端 fetch 请求如何与框架的持久 HTTP 缓存交互。
fetch('https://...', { cache: 'force-cache' | 'no-store' });
no-store
- 每次请求都从远程服务器获取资源,并且不更新缓存。force-cache
- 从缓存(如果存在)或远程服务器获取资源,并更新缓存。
在 Next.js 14 中,如果未提供 cache
选项,则默认使用 force-cache
,除非使用了动态函数或动态配置选项。
在 Next.js 15 中,如果未提供 cache
选项,则默认使用 no-store
。这意味着**fetch 请求默认不会被缓存**。
您仍然可以通过以下方式选择加入 fetch 请求的缓存:
- 在单个
fetch
调用中将cache
选项 设置为force-cache
- 为单个路由将
dynamic
路由配置选项 设置为'force-static'
- 将
fetchCache
路由配置选项 设置为'default-cache'
以覆盖 Layout 或 Page 中的所有fetch
请求,使其使用force-cache
,除非它们明确指定了自己的cache
选项。
GET
路由处理程序不再默认缓存
在 Next 14 中,使用 GET
HTTP 方法的路由处理程序默认会被缓存,除非它们使用了动态函数或动态配置选项。在 Next.js 15 中,GET
函数**默认不会被缓存**。
您仍然可以通过使用静态路由配置选项(例如 export dynamic = 'force-static'
)选择加入缓存。
特殊路由处理程序,如 sitemap.ts
、opengraph-image.tsx
和 icon.tsx
以及其他 元数据文件,默认情况下保持静态,除非它们使用动态函数或动态配置选项。
客户端路由缓存不再默认缓存页面组件
在 Next.js 14.2.0 中,我们引入了实验性的 staleTimes
标志,以允许自定义配置 路由缓存。
在 Next.js 15 中,此标志仍然可用,但我们将默认行为更改为对页面段的 staleTime
设置为 0
。这意味着,当您在应用程序中导航时,客户端将始终反映来自导航过程中激活的页面组件的最新数据。但是,仍然有一些重要的行为保持不变。
- 共享布局数据不会从服务器重新获取,以继续支持 部分渲染。
- 前进/后退导航仍将从缓存中恢复,以确保浏览器可以恢复滚动位置。
loading.js
将继续缓存 5 分钟(或staleTimes.static
配置的值)。
您可以选择加入以前的客户端路由缓存行为,方法是设置以下配置
const nextConfig = {
experimental: {
staleTimes: {
dynamic: 30,
},
},
};
export default nextConfig;
React 19
作为 Next.js 15 版本发布的一部分,我们决定与即将发布的 React 19 版本保持一致。
在 15 版本中,App Router 使用 React 19 RC,并且根据社区反馈,我们还为基于 Pages Router 的 React 18 引入了向后兼容性。如果您使用的是 Pages Router,则可以在准备好时升级到 React 19。
尽管 React 19 仍处于 RC 阶段,但我们在真实世界应用程序中的广泛测试以及与 React 团队的密切合作使我们对它的稳定性充满信心。核心重大更改已得到充分测试,并且不会影响现有的 App Router 用户。因此,我们决定现在将 Next.js 15 发布为稳定版本,以便您的项目为 React 19 GA 做好充分准备。
为了确保过渡尽可能顺利,我们提供了 代码修改和自动化工具 来帮助简化迁移过程。
阅读 Next.js 15 升级指南、React 19 升级指南,并观看 React Conf 主题演讲 以了解更多信息。
Pages Router 在 React 18 上
Next.js 15 维护了对使用 React 18 的 Pages Router 的向后兼容性,允许用户继续使用 React 18,同时受益于 Next.js 15 中的改进。
自第一个候选版本 (RC1) 以来,我们已将重点转移到根据社区反馈包含对 React 18 的支持。这种灵活性使您能够在使用 Pages Router 和 React 18 的情况下采用 Next.js 15,从而更好地控制升级路径。
注意:虽然可以在同一个应用程序中运行 React 18 上的 Pages Router 和 React 19 上的 App Router,但我们不建议这种设置。这样做可能会导致不可预测的行为和类型不一致,因为这两个版本之间的底层 API 和渲染逻辑可能无法完全对齐。
React 编译器(实验性)
React 编译器 是 Meta 的 React 团队创建的一个新的实验性编译器。编译器通过其对普通 JavaScript 语义和 React 规则 的理解,深入了解您的代码,从而可以为您的代码添加自动优化。编译器减少了开发人员必须通过 useMemo
和 useCallback
等 API 进行手动记忆化的次数,从而使代码更简单、更易于维护,并且更不容易出错。
借助 Next.js 15,我们添加了对 React 编译器 的支持。了解有关 React 编译器和 可用的 Next.js 配置选项 的更多信息。
注意:React 编译器目前仅作为 Babel 插件提供,这会导致开发和构建时间变慢。
水合错误改进
Next.js 14.1 对错误消息和水合错误进行了改进。Next.js 15 继续在此基础上构建,并添加了改进的水合错误视图。水合错误现在会显示错误的源代码以及有关如何解决问题的建议。
例如,这是 Next.js 14.1 中之前的错误消息:
Next.js 15 已将其改进为:
Turbopack 开发
我们很高兴地宣布,next dev --turbo
现在已稳定并准备就绪,可以加快您的开发体验。我们一直在将其用于迭代 vercel.com、nextjs.org、v0以及我们所有其他应用程序,并取得了良好的效果。
例如,对于大型 Next.js 应用程序 vercel.com,我们已经看到了
- 本地服务器启动速度提高了高达 76.7%。
- 使用快速刷新时,代码更新速度提高了高达 96.3%。
- 初始路由编译速度提高了高达 45.8%(Turbopack 尚未提供磁盘缓存)。
您可以在我们新的 博文 中了解更多关于 Turbopack Dev 的信息。
静态路由指示器
Next.js 现在在开发过程中显示静态路由指示器,以帮助您识别哪些路由是静态的或动态的。此视觉提示使您能够更轻松地理解页面是如何渲染的,从而优化性能。
您还可以使用 next build 输出查看所有路由的渲染策略。
此更新是我们持续改进 Next.js 可观察性的工作的一部分,使开发人员能够更轻松地监视、调试和优化其应用程序。我们还在开发专用的开发者工具,更多详细信息即将推出。
详细了解 静态路由指示器,它可以被禁用。
使用 unstable_after
执行响应后的代码(实验性)
在处理用户请求时,服务器通常会执行与计算响应直接相关的任务。但是,您可能需要执行诸如日志记录、分析和其他外部系统同步等任务。
由于这些任务与响应没有直接关系,因此用户不应等待它们完成。在响应用户后延迟工作是一个挑战,因为无服务器函数在响应关闭后立即停止计算。
after()
是一个新的实验性 API,它通过允许您安排在响应完成流式传输后处理工作来解决此问题,从而使辅助任务能够在不阻塞主要响应的情况下运行。
要使用它,请将 experimental.after
添加到 next.config.js
中。
const nextConfig = {
experimental: {
after: true,
},
};
export default nextConfig;
然后,在服务器组件、服务器操作、路由处理程序或中间件中导入该函数。
import { unstable_after as after } from 'next/server';
import { log } from '@/app/utils';
export default function Layout({ children }) {
// Secondary task
after(() => {
log();
});
// Primary task
return <>{children}</>;
}
详细了解 unstable_after
。
instrumentation.js
(稳定)
instrumentation
文件及其 register()
API 允许用户访问 Next.js 服务器生命周期,以监控性能、跟踪错误源以及与 OpenTelemetry 等可观察性库深度集成。
此功能现已稳定,并且可以删除 experimental.instrumentationHook
配置选项。
此外,我们还与 Sentry 合作设计了一个新的 onRequestError
钩子,可用于
- 捕获服务器上抛出的所有错误的重要上下文,包括
- 路由器:页面路由器或应用程序路由器
- 服务器上下文:服务器组件、服务器操作、路由处理程序或中间件
- 将错误报告给您喜欢的可观察性提供程序。
export async function onRequestError(err, request, context) {
await fetch('https://...', {
method: 'POST',
body: JSON.stringify({ message: err.message, request, context }),
headers: { 'Content-Type': 'application/json' },
});
}
export async function register() {
// init your favorite observability provider SDK
}
详细了解 onRequestError
函数。
<Form>
组件
新的 <Form>
组件扩展了 HTML <form>
元素,并增加了 预取、客户端导航 和渐进增强功能。
它适用于导航到新页面的表单,例如导致结果页面的搜索表单。
import Form from 'next/form';
export default function Page() {
return (
<Form action="/search">
<input name="query" />
<button type="submit">Submit</button>
</Form>
);
}
<Form>
组件具有以下功能:
- 预取:当表单处于视野中时,会预取 布局 和 加载 UI,从而使导航速度更快。
- 客户端导航:提交时,共享布局和客户端状态会保留。
- 渐进增强:如果 JavaScript 尚未加载,表单仍可以通过完整页面导航工作。
以前,实现这些功能需要大量的手动样板代码。例如
示例
// Note: This is abbreviated for demonstration purposes.
// Not recommended for use in production code.
'use client'
import { useEffect } from 'react'
import { useRouter } from 'next/navigation'
export default function Form(props) {
const action = props.action
const router = useRouter()
useEffect(() => {
// if form target is a URL, prefetch it
if (typeof action === 'string') {
router.prefetch(action)
}
}, [action, router])
function onSubmit(event) {
event.preventDefault()
// grab all of the form fields and trigger a `router.push` with the data URL encoded
const formData = new FormData(event.currentTarget)
const data = new URLSearchParams()
for (const [name, value] of formData) {
data.append(name, value as string)
}
router.push(`${action}?${data.toString()}`)
}
if (typeof action === 'string') {
return <form onSubmit={onSubmit} {...props} />
}
return <form {...props} />
}
详细了解 <Form>
组件。
支持 next.config.ts
Next.js 现在支持 TypeScript next.config.ts
文件类型,并提供 NextConfig
类型以实现自动完成和类型安全的选项。
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
/* config options here */
};
export default nextConfig;
详细了解 Next.js 中的 TypeScript 支持。
自托管改进
在自托管应用程序时,您可能需要更多地控制 Cache-Control
指令。
一个常见的情况是控制为 ISR 页面发送的 stale-while-revalidate
周期。我们已经实现了两个改进:
- 您现在可以在
next.config
中配置expireTime
值。这以前是experimental.swrDelta
选项。 - 将默认值更新为一年,确保大多数 CDN 可以按预期完全应用
stale-while-revalidate
语义。
我们也不再用我们的默认值覆盖自定义 Cache-Control
值,从而可以完全控制并确保与任何 CDN 设置兼容。
最后,我们改进了自托管时的图像优化。以前,我们建议您安装 sharp
以优化 Next.js 服务器上的图像。此建议有时会被忽略。使用 Next.js 15,您不再需要手动安装 sharp
——在使用 next start
或以 独立输出模式 运行时,Next.js 将自动使用 sharp
。
要了解更多信息,请参阅我们关于自托管 Next.js 的新的 演示和教程视频。
增强服务器操作的安全性
服务器操作 是可以从客户端调用的服务器端函数。它们通过在文件顶部添加 'use server'
指令并导出异步函数来定义。
即使服务器操作或实用程序函数在您的代码中没有其他地方导入,它仍然是公开可访问的 HTTP 端点。虽然这种行为在技术上是正确的,但它可能导致此类函数意外泄露。
为了提高安全性,我们引入了以下增强功能:
- 死代码消除:未使用的服务器操作不会将其 ID 公开到客户端 JavaScript 包中,从而减少了包大小并提高了性能。
- 安全的动作 ID:Next.js 现在创建了不可猜测的、不确定的 ID,以允许客户端引用和调用服务器操作。这些 ID 在构建之间会定期重新计算,以增强安全性。
// app/actions.js
'use server';
// This action **is** used in our application, so Next.js
// will create a secure ID to allow the client to reference
// and call the Server Action.
export async function updateUserAction(formData) {}
// This action **is not** used in our application, so Next.js
// will automatically remove this code during `next build`
// and will not create a public endpoint.
export async function deleteUserAction(formData) {}
您仍然应该将服务器操作视为公共 HTTP 端点。了解有关保护服务器操作的更多信息。
优化外部包的打包 (稳定)
打包外部包可以提高应用程序的冷启动性能。在App Router中,默认情况下会打包外部包,并且您可以使用新的serverExternalPackages
配置选项选择退出特定包。
在Pages Router中,默认情况下不会打包外部包,但您可以使用现有的transpilePackages
选项提供要打包的包列表。使用此配置选项,您需要指定每个包。
为了统一 App 和 Pages Router 之间的配置,我们引入了新的选项bundlePagesRouterDependencies
以匹配 App Router 的默认自动打包。如果需要,您可以使用serverExternalPackages
选择退出特定包。
const nextConfig = {
// Automatically bundle external packages in the Pages Router:
bundlePagesRouterDependencies: true,
// Opt specific packages out of bundling for both App and Pages Router:
serverExternalPackages: ['package-name'],
};
export default nextConfig;
了解有关优化外部包的更多信息。
ESLint 9 支持
Next.js 15 还引入了对ESLint 9的支持,这是在 2024 年 10 月 5 日 ESLint 8 结束生命周期之后。
为了确保平滑过渡,Next.js 保持向后兼容,这意味着您可以继续使用 ESLint 8 或 9。
如果您升级到 ESLint 9,并且我们检测到您尚未采用新的配置格式,Next.js 将自动应用ESLINT_USE_FLAT_CONFIG=false
逃生舱以简化迁移。
此外,在运行next lint
时,将删除—ext
和—ignore-path
等已弃用的选项。请注意,ESLint 最终将在 ESLint 10 中不允许这些旧配置,因此我们建议您尽快开始迁移。
有关这些更改的更多详细信息,请查看迁移指南。
作为此更新的一部分,我们还将eslint-plugin-react-hooks
升级到v5.0.0
,其中引入了用于 React Hooks 用法的新规则。您可以在[email protected] 的更改日志中查看所有更改。
开发和构建改进
服务器组件 HMR
在开发过程中,保存服务器组件时会重新执行它们。这意味着,对您的 API 端点或第三方服务的任何fetch
请求也会被调用。
为了提高本地开发性能并降低计费 API 调用的潜在成本,我们现在确保热模块替换 (HMR) 可以重用先前渲染的fetch
响应。
了解有关服务器组件 HMR 缓存的更多信息。
App Router 的更快的静态生成
我们优化了静态生成以缩短构建时间,尤其是在具有缓慢网络请求的页面上。
以前,我们的静态优化过程会渲染页面两次——一次是为了生成客户端导航的数据,第二次是为了渲染初始页面访问的 HTML。现在,我们重用第一次渲染,省略了第二次传递,减少了工作量和构建时间。
此外,静态生成工作程序现在在页面之间共享fetch
缓存。如果fetch
调用未选择退出缓存,则其他由同一工作程序处理的页面会重用其结果。这减少了对相同数据的请求次数。
高级静态生成控制 (实验性)
我们添加了对更高级别控制静态生成过程的实验性支持,这些高级用例将受益于更大的控制权。
除非您有特定要求,否则我们建议您坚持使用当前的默认值,因为这些选项会导致资源使用增加以及由于并发性增加而可能导致内存不足错误。
const nextConfig = {
experimental: {
// how many times Next.js will retry failed page generation attempts
// before failing the build
staticGenerationRetryCount: 1
// how many pages will be processed per worker
staticGenerationMaxConcurrency: 8
// the minimum number of pages before spinning up a new export worker
staticGenerationMinPagesPerWorker: 25
},
}
export default nextConfig;
了解有关静态生成选项的更多信息。
其他更改
- [重大更改] next/image:已删除
squoosh
,转而使用sharp
作为可选依赖项(PR) - [重大更改] next/image:将默认
Content-Disposition
更改为attachment
(PR) - [重大更改] next/image:当
src
具有前导或尾随空格时出错(PR) - [重大更改] 中间件:应用
react-server
条件以限制不推荐的 React API 导入(PR) - [重大更改] next/font:已删除对外部
@next/font
包的支持(PR) - [重大更改] next/font:已删除
font-family
哈希(PR) - [重大更改] 缓存:
force-dynamic
现在将no-store
设置为 fetch 缓存的默认值(PR) - [重大变更] 配置:默认启用
swcMinify
(PR)、missingSuspenseWithCSRBailout
(PR) 和outputFileTracing
(PR) 行为,并移除已弃用的选项。 - [重大变更] 移除 Speed Insights 的自动检测功能(现在必须使用专用的 @vercel/speed-insights 包)(PR)
- [重大变更] 移除动态站点地图路由的
.xml
扩展名,并统一开发和生产环境中的站点地图 URL (PR) - [重大变更] 我们已弃用在 App Router 中导出
export const runtime = "experimental-edge"
。用户现在应该切换到export const runtime = "edge"
。我们添加了一个 代码修改工具 来执行此操作 (PR) - [重大变更] 在渲染期间调用
revalidateTag
和revalidatePath
现在将抛出错误 (PR) - [重大变更]
instrumentation.js
和middleware.js
文件现在将使用打包的 React 包 (PR) - [重大变更] 最低所需的 Node.js 版本已更新至 18.18.0 (PR)
- [重大变更]
next/dynamic
:已移除已弃用的suspense
属性,并且当组件在 App Router 中使用时,它将不再插入空的 Suspense 边界 (PR) - [重大变更] 在 Edge Runtime 上解析模块时,将不会应用
worker
模块条件 (PR) - [重大变更] 禁止在服务器组件中将
ssr: false
选项与next/dynamic
一起使用 (PR) - [改进] 元数据:在 Vercel 上托管时,更新了
metadataBase
的环境变量回退 (PR) - [改进] 修复了
optimizePackageImports
中混合命名空间和命名导入的 tree-shaking 问题 (PR) - [改进] 并行路由:为不匹配的通配符路由提供所有已知参数 (PR)
- [改进] 配置项
bundlePagesExternals
现在已稳定,并重命名为bundlePagesRouterDependencies
。 - [改进] 配置项
serverComponentsExternalPackages
现在已稳定,并重命名为serverExternalPackages
。 - [改进] create-next-app:新项目默认忽略所有
.env
文件 (PR) - [改进]
outputFileTracingRoot
、outputFileTracingIncludes
和outputFileTracingExcludes
已从实验性升级为稳定版本 (PR) - [改进] 避免将全局 CSS 文件与树中更深层的 CSS 模块文件合并 (PR)
- [改进] 可以通过
NEXT_CACHE_HANDLER_PATH
环境变量指定缓存处理器 (PR) - [改进] Pages Router 现在同时支持 React 18 和 React 19 (PR)
- [改进] 如果启用了检查器,错误覆盖层现在会显示一个按钮来复制 Node.js 检查器 URL (PR)
- [改进] App Router 上的客户端预取现在使用
priority
属性 (PR) - [改进] Next.js 现在提供了一个
unstable_rethrow
函数,用于在 App Router 中重新抛出 Next.js 内部错误 (PR) - [改进] 现在可以在静态页面中使用
unstable_after
(PR) - [改进] 如果在 SSR 期间使用了
next/dynamic
组件,则会预取该块 (PR) - [改进] App Router 现在支持
esmExternals
选项 (PR) - [改进] 可以使用
experimental.allowDevelopmentBuild
选项在进行调试时允许使用NODE_ENV=development
以及next build
(PR)。 - [改进] 服务器操作转换现在在页面路由器中被禁用(PR)。
- [改进] 构建 Worker 现在会在它们退出时停止构建挂起(PR)。
- [改进] 从服务器操作重定向时,重新验证现在将正确应用(PR)。
- [改进] 现在在 Edge Runtime 上,并行路由的动态参数得到正确处理(PR)。
- [改进] 静态页面现在将在初始加载后尊重 staleTime(PR)。
- [改进]
vercel/og
更新并修复了内存泄漏问题(PR)。 - [改进] 更新了补丁时间,以允许使用
msw
等包进行 API 模拟(PR)。 - [改进] 预渲染页面应使用静态 staleTime(PR)。
要了解更多信息,请查看 升级指南。
贡献者
Next.js 是超过 3000 位独立开发人员、谷歌和 Meta 等行业合作伙伴以及我们在 Vercel 的核心团队共同努力的结果。此版本由以下人员贡献:
- Next.js 团队:Andrew,Hendrik,Janka,Jiachi,Jimmy,Jiwon,JJ,Josh,Sam,Sebastian,Sebbie,Shu,Wyatt 和 Zack。
- Turbopack 团队:Alex,Benjamin,Donny,Maia,Niklas,Tim,Tobias 和 Will。
- Next.js 文档团队:Delba,Rich,Ismael,以及Lee。
特别感谢 @AbhiShake1、@Aerilym、@AhmedBaset、@AnaTofuZ、@Arindam200、@Arinji2、@ArnaudFavier、@ArnoldVanN、@Auxdible、@B33fb0n3、@Bhavya031、@Bjornnyborg、@BunsDev、@CannonLock、@CrutchTheClutch、@DeepakBalaraman、@DerTimonius、@Develliot、@EffectDoplera、@Ehren12、@Ethan-Arrowood、@FluxCapacitor2、@ForsakenHarmony、@Francoscopic、@Gomah、@GyoHeon、@Hemanshu-Upadhyay、@HristovCodes、@HughHzyb、@IAmKushagraSharma、@IDNK2203、@IGassmann、@ImDR、@IncognitoTGT、@Jaaneek、@JamBalaya56562、@Jeffrey-Zutt、@JohnGemstone、@JoshuaKGoldberg、@Julian-Louis、@Juneezee、@KagamiChan、@Kahitar、@KeisukeNagakawa、@KentoMoriwaki、@Kikobeats、@KonkenBonken、@Kuboczoch、@Lada496、@LichuAcu、@LorisSigrist、@Lsnsh、@Luk-z、@Luluno01、@M-YasirGhaffar、@Maaz-Ahmed007、@Manoj-M-S、@ManuLpz4、@Marukome0743、@MaxLeiter、@MehfoozurRehman、@MildTomato、@MonstraG、@N2D4、@NavidNourani、@Nayeem-XTREME、@Netail、@NilsJacobsen、@Ocheretovich、@OlyaPolya、@PapatMayuri、@PaulAsjes、@PlagueFPS、@ProchaLu、@Pyr33x、@QiuranHu、@RiskyMH、@Sam-Phillemon9493、@Sayakie、@Shruthireddy04、@SouthLink、@Strift、@SukkaW、@Teddir、@Tim-Zj、@TrevorSayre、@Unsleeping、@Willem-Jaap、@a89529294、@abdull-haseeb、@abhi12299、@acdlite、@actopas、@adcichowski、@adiguno、@agadzik、@ah100101、@akazwz、@aktoriukas、@aldosch、@alessiomaffeis、@allanchau、@alpedia0、@amannn、@amikofalvy、@anatoliik-lyft、@anay-208、@andrii-bodnar、@anku255、@ankur-dwivedi、@aralroca、@archanaagivale30、@arlyon、@atik-persei、@avdeev、@baeharam、@balazsorban44、@bangseongbeom、@begalinsaf、@bennettdams、@bewinsnw、@bgw、@blvdmitry、@bobaaaaa、@boris-szl、@bosconian-dynamics、@brekk、@brianshano、@cfrank、@chandanpasunoori、@chentsulin、@chogyejin、@chrisjstott、@christian-bromann、@codeSTACKr、@coderfin、@coltonehrman、@controversial、@coopbri、@creativoma、@crebelskydico、@crutchcorn、@darthmaim、@datner、@davidsa03、@delbaoliveira、@devjiwonchoi、@devnyxie、@dhruv-kaushik、@dineshh-m、@diogocapela、@dnhn、@domdomegg、@domin-mnd、@dvoytenko、@ebCrypto、@ekremkenter、@emmerich、@flybayer、@floriangosse、@forsakenharmony、@francoscopic、@frys、@gabrielrolfsen、@gaojude、@gdborton、@greatvivek11、@gnoff、@guisehn、@GyoHeon、@hamirmahal、@hiro0218、@hirotomoyamada、@housseindjirdeh、@hungdoansy、@huozhi、@hwangstar156、@iampoul、@ianmacartney、@icyJoseph、@ijjk、@imddc、@imranolas、@iscekic、@jantimon、@jaredhan418、@jeanmax1me、@jericopulvera、@jjm2317、@jlbovenzo、@joelhooks、@joeshub、@jonathan-ingram、@jonluca、@jontewks、@joostmeijles、@jophy-ye、@jordienr、@jordyfontoura、@kahlstrm、@karlhorky、@karlkeefer、@kartheesan05、@kdy1、@kenji-webdev、@kevva、@khawajaJunaid、@kidonng、@kiner-tang、@kippmr、@kjac、@kjugi、@kshehadeh、@kutsan、@kwonoj、@kxlow、@leerob、@lforst、@li-jia-nan、@liby、@lonr、@lorensr、@lovell、@lubieowoce、@luciancah、@luismiramirez、@lukahartwig、@lumirlumir、@luojiyin1987、@mamuso、@manovotny、@marlier、@mauroaccornero、@maxhaomh、@mayank1513、@mcnaveen、@md-rejoyan-islam、@mehmetozguldev、@mert-duzgun、@mirasayon、@mischnic、@mknichel、@mobeigi、@molebox、@mratlamwala、@mud-ali、@n-ii-ma、@n1ckoates、@nattui、@nauvalazhar、@neila-a、@neoFinch、@niketchandivade、@nisabmohd、@none23、@notomo、@notrab、@nsams、@nurullah、@okoyecharles、@omahs、@paarthmadan、@pathliving、@pavelglac、@penicillin0、@phryneas、@pkiv、@pnutmath、@qqww08、@r34son、@raeyoung-kim、@remcohaszing、@remorses、@rezamauliadi、@rishabhpoddar、@ronanru、@royalfig、@rubyisrust、@ryan-nauman、@ryohidaka、@ryota-murakami、@s-ekai、@saltcod、@samcx、@samijaber、@sean-rallycry、@sebmarkbage、@shubh73、@shuding、@sirTangale、@sleevezip、@slimbde、@soedirgo、@sokra、@sommeeeer、@sopranopillow、@souporserious、@srkirkland、@steadily-worked、@steveluscher、@stipsan、@styfle、@stylessh、@syi0808、@symant233、@tariknh、@theoludwig、@timfish、@timfuhrmann、@timneutkens、@tknickman、@todor0v、@tokkiyaa、@torresgol10、@tranvanhieu01012002、@txxxxc、@typeofweb、@unflxw、@unstubbable、@versecafe、@vicb、@vkryachko、@wbinnssmith、@webtinax、@weicheng95、@wesbos、@whatisagi、@wiesson、@woutvanderploeg、@wyattjoh、@xiaohanyu、@xixixao、@xugetsu、@yosefbeder、@ypessoa、@ytori、@yunsii、@yurivangeffen、@z0n、@zce、@zhawtof、@zsh77 和 @ztanner 的帮助!