Back返回博客

Next.js 12

Next.js 12 引入了全新的 Rust 编译器、中间件 (beta)、React 18 支持、原生 ESM 支持、URL 导入、React 服务端组件 (alpha) 等特性!

正如我们在 Next.js 大会 上宣布的,Next.js 12 是我们有史以来最重磅的发布:

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

通过 Rust 编译器实现更快的构建和热更新

我们致力于让每个 Next.js 应用的生产构建更快,并在本地开发中获得即时反馈。Next.js 12 包含一个全新的 Rust 编译器,充分利用了原生编译的优势。

我们的 Rust 编译器基于 SWC 构建,这是一个面向下一代快速工具的开源平台。我们优化了打包和编译过程,本地热更新速度提升约 3 倍,生产构建速度提升约 5 倍。其他改进和特性包括:

在大型 Next.js 代码库中使用新 Rust 编译器的效果

在大型 Next.js 代码库中使用新 Rust 编译器的效果

  • 针对大型代码库的进一步速度优化:我们已在全球一些最大的 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 KangParcel 贡献者 Maia Teegarden 外,我们还在持续投资 Rust 生态系统。如果您有 Rust 开发经验,欢迎申请加入我们的团队

更多信息请观看 Next.js 大会上的演示

中间件介绍

中间件让您能够以代码优先的方式配置。这为 Next.js 提供了完全的灵活性,因为您可以在请求完成前运行代码。根据用户的传入请求,您可以通过重写、重定向、添加标头甚至流式传输 HTML 来修改响应。

中间件为 Next.js 提供了完全的灵活性

中间件为 Next.js 提供了完全的灵活性

中间件可用于任何需要在一组页面间共享逻辑的场景,包括:

中间件使用严格运行时,支持标准 Web API 如 fetch。这在使用 next start 时开箱即用,在 Vercel 等边缘平台上也能使用 Edge 中间件

要在 Next.js 中使用中间件,可以创建文件 pages/_middleware.js。以下示例使用了标准 Web API Response (MDN):

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

更多信息请观看 Next.js 大会上的演示查阅文档

为 React 18 做准备

React 18 将新增 Suspense、自动批处理更新、startTransition 等 API,以及支持 React.lazy 的服务端流式渲染新 API。

我们一直与 Facebook 的 React 团队密切合作,为 React 18 的稳定版发布做准备。现在您可以在 Next.js 12 中通过实验性标志体验这些特性。

Terminal
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 Server Components)

React 服务端组件允许我们在服务端渲染所有内容,包括组件本身。这与服务端渲染 (SSR) 有本质区别——后者只是在服务端预生成 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 Modules Support and URL Imports)

ES 模块为 JavaScript 带来了官方标准化模块系统,所有主流浏览器和 Node.js 均已支持。

该标准通过减小包体积和 JavaScript 打包文件推动生态进步,最终带来更好的用户体验。随着 JavaScript 生态从 Common JS(旧标准)向 ES 模块过渡,我们致力于帮助开发者逐步采用这些改进,同时避免不必要的破坏性变更。

Next.js 11.1 开始,我们实验性支持优先使用 ES 模块而非 CommonJS 模块。在 Next.js 12 中,这已成为默认行为。导入仅提供 CommonJS 的 NPM 模块仍受支持。

URL 导入 (URL Imports)

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 的演示视频查阅文档

针对爬虫的 ISR 回退策略 (Bot-Aware ISR Fallback)

当前使用 fallback: true增量静态再生 (ISR) 会在首次请求未生成页面时先显示回退状态。要阻止页面加载(服务端渲染),您需要使用 fallback: 'blocking'

在 Next.js 12 中,网络爬虫(如搜索引擎机器人) 会自动使用 fallback: true 服务端渲染 ISR 页面,同时仍对非爬虫 User-Agent 保持原有回退行为。这能防止爬虫索引加载状态。

使用 AVIF 实现更小图片 (Smaller images using AVIF)

内置的图片优化 API 现支持 AVIF 格式,相比 WebP 可减小 20% 体积。

AVIF 图片优化耗时可能比 WebP 长,因此我们通过 next.config.js 中的新属性 images.formats 将其设为可选功能:

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

该格式列表会根据请求的 Accept 头按需确定优化格式。AVIF 优先,若浏览器支持 AVIF 则使用;否则若支持 WebP 则使用 WebP(参见 WebP 支持情况);若均不支持则返回原格式。

输出文件追踪 (Output File Tracing)

Next.js 8 引入了 target 选项,允许在构建时通过 webpack 打包所有依赖,将 Next.js 页面输出为独立 JavaScript 包。我们很快意识到这不是理想方案,转而创建了 @vercel/nft。过去两年,Vercel 平台的所有部署都在使用 @vercel/nft

现在,我们默认将这些改进直接集成到 Next.js 框架中,适用于所有部署平台,提供了比 target 选项更优的方案。

Next.js 12 自动使用 @vercel/nft 追踪每个页面和 API 路由所需的文件,并将追踪结果输出到 next build 旁,让集成方能直接利用这些自动生成的追踪数据。

这些变更也优化了使用 Docker 等工具通过 next start 部署的应用。借助 @vercel/nft,未来我们将实现 Next.js 输出的完全独立——运行应用时无需安装任何依赖,大幅减小 Docker 镜像体积。

@vercel/nft 引入 Next.js 取代了 target 方案,因此在 Next.js 12 中 target 已被弃用。查阅文档了解更多。

其他改进 (Other Improvements)

  • 添加 pages/_app.jspages/_document.js 现在会自动替换内置版本,无需重启 Next.js CLI
  • ESLint 集成现支持通过 --file 标志在 next lint单文件 lint
  • Next.js 12 支持设置自定义 tsconfig.json 路径
  • 现支持使用 next.config.mjs 以 ES 模块形式编写配置
  • 对 getStaticProps 的重复飞行请求现会去重
  • 静态页面检查现在使用共享 worker 池运行
  • Fast Refresh 现使用 WebSocket 连接而非 EventSource 连接

破坏性变更 (Breaking Changes)

  • 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 版本)

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

社区 (Community)

五年前,我们向公众发布了 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