跳到内容
返回博客

2021 年 10 月 26 日,星期二

Next.js 12

发布者

正如我们在Next.js Conf上宣布的那样,Next.js 12 是我们有史以来最大的版本

立即运行 npm i next@latest 进行更新。

使用 Rust 编译器实现更快的构建和快速刷新

我们希望使每个 Next.js 应用程序的生产环境构建速度更快,并在本地开发中获得即时反馈。Next.js 12 包含一个全新的 Rust 编译器,它利用了原生编译的优势。

我们的 Rust 编译器构建于 SWC,这是一个用于下一代快速工具的开放平台。我们优化了捆绑和编译,本地刷新速度提高了约 3 倍,生产环境构建速度提高了约 5 倍。其他改进和功能包括:

Results from using the new Rust compiler with large Next.js codebases.
使用新的 Rust 编译器处理大型 Next.js 代码库的结果。
  • 大型代码库的进一步速度提升: 我们已经使用世界上一些最大的 Next.js 代码库验证了 Rust 编译器。
  • 改进了性能的可观察性: Next.js 现在在控制台中输出客户端和服务器编译的快速刷新计时,包括编译的模块和文件数量。
  • 底层的 webpack 改进: 我们对 webpack 进行了大量改进,包括优化快速刷新和使按需条目更可靠。

使用 Rust 进行编译比 Babel 快 17 倍,并且默认使用 Next.js 12 启用,取代了 JavaScript 和 TypeScript 文件的转换。这意味着我们必须将 Next.js 中的 Babel 转换移植到 Rust,包括用于实现 styled-jsx 转换的全新的 Rust CSS 解析器

新的 Rust 编译器是向后兼容的。如果您有现有的 Babel 配置,您将自动选择退出。我们计划很快移植对流行库(如 styled-componentsemotionrelay)的解析。如果您正在使用自定义 Babel 设置,请分享您的配置

您还可以选择启用 Rust 编译器进行代码压缩。这比 Terser 快 7 倍。代码压缩是可选的,直到它被彻底验证,因为它取代了多年的基础设施。

next.config.js
module.exports = {
  swcMinify: true,
};

除了聘请 SWC 的创建者 DongYoon Kang 和 Parcel 的贡献者 Maia Teegarden 之外,我们还在继续投资 Rust 生态系统。如果您有 Rust 工作经验,请申请加入我们的团队

有关更多信息,请观看我们在 Next.js Conf 上的演示

中间件介绍

中间件使您可以使用代码而非配置。这使您在 Next.js 中具有完全的灵活性,因为您可以在请求完成之前运行代码。根据用户的传入请求,您可以通过重写、重定向、添加标头甚至流式传输 HTML 来修改响应。

Middleware gives you complete flexibility inside Next.js.
中间件为您在 Next.js 内部提供了完全的灵活性。

中间件可用于为一组页面共享逻辑的任何内容,包括:

中间件使用严格的运行时,支持标准的 Web API,如 fetch。这在使用 next start 以及在 Vercel 等边缘平台(使用 Edge Middleware)时开箱即用。

要在 Next.js 中使用中间件,您可以创建一个文件 pages/_middleware.js。在此示例中,我们使用标准的 Web API Response (MDN)

pages/_middleware.js
export function middleware(req, ev) {
  return new Response('Hello, world!');
}

有关更多信息,请观看我们在 Next.js Conf 上的演示,并查看文档

为 React 18 做准备

React 18 将添加诸如 Suspense、自动批量更新、API(如 startTransition)以及新的服务器渲染流式 API(支持 React.lazy)等功能。

我们一直与 Facebook 的 React 团队密切合作,为 React 18 稳定版发布做准备。我们正在 Next.js 12 中通过实验性标志提供这些功能以供试用。

终端
npm install react@alpha react-dom@alpha

服务端流式传输

React 18 中的并发功能包括对服务端 Suspense 和 SSR 流式传输支持的内置支持。这允许您使用 HTTP 流式传输来服务端渲染页面。这是 Next.js 12 中的一个实验性功能,但一旦启用,SSR 将使用与中间件相同的严格运行时。

要启用,请使用实验性标志 concurrentFeatures: true

next.config.js
module.exports = {
  experimental: {
    concurrentFeatures: true,
  },
};

React 服务器组件

React 服务器组件允许我们在服务器上渲染所有内容,包括组件本身。这与服务端渲染从根本上不同,后者是在服务器上预生成 HTML。使用服务器组件,零客户端 JavaScript 是必需的,从而加快页面渲染速度。这改善了应用程序的用户体验,将服务端渲染的最佳部分与客户端交互性相结合。

next.config.js
module.exports = {
  experimental: {
    concurrentFeatures: true,
    serverComponents: true,
  },
};

Next.js 现在允许您在组件级别进行数据获取,所有这些都表示为 JSX。通过使用 React 服务器组件,我们可以简化事情。不再需要像 getServerSidePropsgetStaticProps 这样的特殊函数。这与将数据获取与组件并置的 React Hooks 模型保持一致。

您可以将任何 Next.js 页面重命名为 .server.js 以创建服务器组件,并在服务器组件中直接导入客户端组件。这些客户端组件将水合并变为交互式,因此您可以添加诸如点赞之类的功能。

我们目前正在 Next.js 中开发服务端 Suspense、选择性水合和流式渲染,并将在未来的博客文章中分享我们的进展。

特别感谢我们在 Google Aurora 团队的合作者 Kara EricksonGerald Monaco 在 React 18 和服务器组件方面的工作。

有关更多信息,请观看我们在 Next.js Conf 上的演示,并查看文档

ES 模块支持和 URL 导入

ES 模块为 JavaScript 带来了官方的标准化模块系统。所有主流浏览器以及 Node.js 都支持它们。

该标准通过实现更小的包大小和 JavaScript 包,从而推动 Web 生态系统向前发展,最终带来更好的用户体验。随着 JavaScript 生态系统从 Common JS(旧标准)过渡到 ES 模块,我们致力于帮助开发人员逐步采用这些改进,而无需不必要的重大更改。

Next.js 11.1 开始,我们添加了对优先于 CommonJS 模块的 ES 模块 的实验性支持。在 Next.js 12 中,这现在是默认设置。仍然支持导入仅提供 CommonJS 的 NPM 模块。

URL 导入

Next.js 12 包括通过 URL 导入 ES 模块的实验性支持,无需安装或单独的构建步骤。

URL 导入允许您直接通过 URL 使用任何包。这使 Next.js 能够像处理本地依赖项一样处理远程 HTTP(S) 资源。

如果检测到 URL 导入,Next.js 将生成一个 next.lock 文件来跟踪远程资源。URL 导入在本地缓存,以确保您仍然可以离线工作。Next.js 支持客户端和服务器 URL 导入。

要选择启用,请在 next.config.js 中添加允许的 URL 前缀

next.config.js
module.exports = {
  experimental: {
    urlImports: ['https://cdn.skypack.dev'],
  },
};

然后,您可以直接从 URL 导入模块

import confetti from 'https://cdn.skypack.dev/canvas-confetti';

任何提供 ES 模块的 CDN 都可以工作,包括像 Framer 这样的无代码和设计工具

欲了解更多信息,请观看我们在 Next.js Conf 上的演示,并查看文档

Bot 感知 ISR 回退

目前,使用 fallback: true增量静态再生 会在首次请求尚未生成的页面时,渲染页面内容之前的回退状态。要阻止页面加载(服务器渲染),您需要使用 fallback: 'blocking'

在 Next.js 12 中,网络爬虫(例如,搜索机器人) 将自动服务器渲染使用 fallback: true 的 ISR 页面,同时仍然为非爬虫 User-Agent 提供回退状态的先前行为。这可以防止爬虫索引加载状态。

使用 AVIF 的更小图片

内置的图像优化 API 现在支持 AVIF 图像,与 WebP 相比,图像体积缩小 20%。

与 WebP 相比,AVIF 图像可能需要更长的时间来优化,因此我们使用 next.config.js 中的新 images.formats 属性使此功能成为可选项

next.config.js
module.exports = {
  images: {
    formats: ['image/avif', 'image/webp'],
  },
};

此格式列表用于根据请求的 Accept 标头确定按需优化的图像格式。由于 AVIF 排在第一位,如果浏览器支持 AVIF,则将提供 AVIF。否则,如果浏览器支持 WebP,则将提供 WebP。如果两种格式都不支持,则将提供原始图像格式。

输出文件追踪

在 Next.js 8 中,我们引入了 target 选项。这允许通过在构建期间使用 webpack 打包所有依赖项,将 Next.js 页面作为独立的 JavaScript 包输出。我们很快意识到这并不理想,因此创建了 @vercel/nft@vercel/nft 已在 Vercel 平台上的所有部署中使用了 2 年多。

现在,我们将这些改进直接默认引入 Next.js 框架中,适用于所有部署平台,与 target 选项相比,提供了一种显著改进的方法。

Next.js 12 使用 @vercel/nft 自动追踪每个页面和 API 路由所需的文件,并将这些追踪结果输出到 next build 输出旁边,从而使集成商能够利用 Next.js 自动提供的追踪信息。

这些更改还优化了使用 Docker 等工具通过 next start 部署的应用程序。通过利用 @vercel/nft,我们将来能够使 Next.js 输出独立运行。无需安装任何依赖项即可运行应用程序,从而大大减小 Docker 镜像大小。

@vercel/nft 引入 Next.js 取代了 target 方法,使 target 在 Next.js 12 中被弃用。查看文档了解更多信息。

其他改进

  • 现在,将 pages/_app.jspages/_document.js 添加到您的应用程序会自动替换内置版本,而无需重启 Next.js CLI。
  • ESLint 集成现在支持在 next lint 中使用 --file 标志进行单文件 linting
  • Next.js 12 现在支持设置自定义 tsconfig.json 路径。
  • 现在支持使用 next.config.mjs 将配置编写为 ES 模块。
  • 现在为 getStaticProps 对正在进行的请求进行去重。
  • 现在使用共享工作池运行静态页面检查。
  • 快速刷新现在使用 WebSocket 连接而不是 EventSource 连接。

重大变更

  • Next.js 11 中将 webpack 5 作为默认设置后,我们现在已正式移除 webpack 4。我们与社区紧密合作,以确保平稳过渡到 webpack 5。
  • next.config.js 中的 target 不再需要。
  • next/image 现在使用 span 作为包装元素,而不是 div
  • 最低 Node.js 版本已从 12.0.0 提升到 12.22.0,这是第一个支持原生 ES 模块的 Node.js 版本。

要了解更多信息,请查看升级指南

社区

五年前,我们公开发布了 Next.js。我们着手构建一个零配置的 React 框架,以简化您的开发者体验。回顾过去,令人难以置信的是,社区是如何发展壮大的,以及我们共同交付了什么。让我们继续前进。

Next.js 是 超过 1,800 位个人开发者、Google 和 Facebook 等行业合作伙伴以及我们核心团队共同努力的成果。

此版本由以下贡献者共同贡献:@ka2n, @housseindjirdeh, @rojserbest, @lobsterkatie, @thibautsabot, @javivelasco, @sokra, @rishabhpoddar, @kdy1, @huozhi, @georgegach, @ionut-botizan, @paul-creates, @TimBarley, @kimizuy, @devknoll, @matamatanot, @christianvuerings, @pgrodrigues, @mohamedbhy, @AlfonzAlfonz, @kara, @molebox, @angelopoole, @oste, @genetschneider, @jantimon, @kyliau, @mxschmitt, @PhattOZ, @finn-orsini, @kriswuollett, @harryheman, @GustavoEdinger, @AryanBeezadhur, @Blevs, @colevscode, @atcastle, @ijjk, @velocity23, @jonowu, @timneutkens, @whitep4nth3r, @micro-chipset, @TyMick, @padmaia, @arthurdenner, @vitorbal, @zNeb, @jacksonhardaker, @shuding, @kylemh, @Bundy-Mundi, @ctjlewis, @thien-do, @leerob, @Dev-CasperTheGhost, @janicklas-ralph, @rezathematic, @KonstHardy, @fracture91, @lorensr, @Sheraff, @HaNdTriX, @emilio, @oluan, @ddzieduch, @colinclerk, @x4th, @volcareso, @oiva, @sinchang, @scottrepreneur, @smakosh, @catnose99, @adrienharnay, @donsn, @andersonleite, @msp5382, @tim-hanssen, @appsplash99, @alexvilchis, @RobEasthope, @royal, @Perry-Olsson, @well-balanced, @mrmckeb, @buraksakalli, @espipj, @prateekbh, @AleksaC, @eungyeole, 和 @rgabs