Back返回博客

Next.js 13.1 版本发布

Next.js 13.1 带来了应用目录改进、内置模块转译、API 路由的稳定边缘运行时,以及对 Turbopack 支持的诸多优化。

Next.js 13.1 包含了对 pages/(稳定版)和 app/(测试版)目录的双重改进:

立即通过以下命令更新:

终端
npm i next@latest react@latest react-dom@latest eslint-config-next@latest

app 目录可靠性提升与支持增强

在 Next.js 13 中,我们推出了新的 app 目录(测试版)。这套全新的路由和数据获取系统可以与现有的 pages 目录逐步共存。

app 目录提供诸多优势,包括增强的布局系统、组件/测试/样式的同位置存放、组件级数据获取等。基于社区反馈和早期测试,我们针对 app 目录的可靠性做出了多项改进:

  • 消除布局 DIV:此前 app 目录会添加额外的 <div> 元素来实现导航时的滚动定位。13.1 版本不再生成这些元素,同时保留了滚动行为。
  • TypeScript 插件:我们开发了新的 TypeScript 插件,提供页面和布局配置建议,将文档直接集成至 IDE,并针对服务端组件和客户端组件(如防止在服务端组件使用 useState)给出使用提示。了解更多
  • 可靠性提升:修复了大量问题,包括改进 CSS 模块支持、正确去重布局和页面的 cache()fetch()、内存泄漏等
  • 减少客户端 JavaScriptapp 目录现在比 pages 目录减少 9.3kB 客户端 JavaScript。无论添加 1 个还是 1000 个服务端组件,这个基准值都不会增加。React 运行时暂时略有增大,这是由于 React 服务端组件运行时接管了原先由 Next.js 处理的机制。我们正在进一步优化。
pages/app/差异
首次加载 JS 总量基准值-9.3kB减少 12.1%
Next.js 运行时基准值-12kB减少 56.8%
React 运行时基准值+2.7kB增加 5.2%

我们很高兴能持续推进 app 目录的稳定性。测试版文档 已根据社区反馈进行了数百项更新。

内置模块转译(稳定版)

现在可以指定需要转译和打包的本地包(如 monorepo)或外部依赖(node_modules)。这个内置功能取代了流行的 next-transpile-modules 包。

/** @type {import('next').NextConfig} */
const nextConfig = {
  transpilePackages: ['@acme/ui', 'lodash-es'],
};
 
module.exports = nextConfig;

感谢 Pierre de la Martinière (@martpie) 对该包的贡献,以及协助确保内置功能满足社区需求。

导入解析优化以减小包体积

许多流行的 npm 包使用 "barrel 文件" 来提供重新导出其他模块的单一入口。例如:

@acme/ui/index.ts
export { default as Button } from './dist/Button';
export { default as Slider } from './dist/Slider';
export { default as Dropdown } from './dist/Dropdown';

这使得包的使用者可以单行导入:

import { Button, Slider, Dropdown } from '@acme/ui';

虽然打包器能理解这些 barrel 文件并移除未使用的重新导出(称为"死代码消除"),但此过程需要解析/编译所有被重新导出的文件。某些 npm 包的 barrel 文件可能重新导出数千个模块,这会拖慢编译速度。这些库推荐使用 babel-plugin-transform-imports 解决此问题,但对于 SWC 用户此前没有对应方案。我们新增了名为 modularizeImports 的内置 SWC 转换功能。

这项新设置使 SWC 能根据定义模式转换导入语句。例如上述三个组件的导入会自动转换为直接导入,开发者无需手动修改:

// 转换前(使用 barrel 文件)
import { Button, Slider, Dropdown } from '@acme/ui';
 
// 转换后(使用插件模块化导入)
import Button from '@acme/ui/dist/Button';
import Slider from '@acme/ui/dist/Slider';
import Dropdown from '@acme/ui/dist/Dropdown';

通过 next.config.js 中的 modularizeImports 选项启用此转换:

next.config.js
module.exports = {
  modularizeImports: {
    '@acme/ui': {
      transform: '@acme/ui/dist/{{member}}',
    },
  },
};

@mui/icons-materiallodash 使用此转换可以跳过未使用文件的编译。了解更多

查看演示了解实际效果。

轻量级 Node.js 边缘运行时,现稳定支持 API 路由

Next.js 中的边缘运行时使用 Node.js API 的严格子集(如 RequestResponse 等),兼容 Vercel 等边缘计算平台或自托管环境。这些 API 可在包括浏览器在内的任何环境运行,实现"一次学习,随处编写"。

pages/api/hello.ts
// 不再需要 "experimental-" 前缀
export const config = {
  runtime: 'edge',
};
 
export default function handler(req: Request) {
  return new Response('Hello World');
}

Next.js 中间件默认使用这个轻量边缘运行时以获得更好性能。由于中间件能在每个请求前运行,轻量级运行时对保证低延迟至关重要。在 Next.js 12.2 中,我们增加了对 API 路由 的可选支持。

13.1 版本中,边缘运行时现已在 API 路由中稳定可用。自托管时,使用边缘运行时的中间件和 API 路由默认作为单区域工作负载运行(通过 next start)。在 Vercel 上,Next.js 中间件和 API 路由会通过 Vercel Edge Functions 全球部署以实现最低延迟。Vercel Edge Functions 也已正式发布

Turbopack 改进

自 Next.js 13 发布 Turbopack alpha 版以来,我们专注于提升可靠性、增加最受期待的功能支持,以及制定插件和其他框架使用的计划。

从 Next.js 13.0.0 开始,Turbopack:

  • 支持 PostCSS(包括 Tailwind CSS)
  • 支持 next/image
  • 支持 @next/font(Google 字体)
  • 支持从动态 import() 语句加载 CSS
  • 支持 CSS 源映射(感谢 @ahabhgk贡献
  • 改进 next dev 错误覆盖层的错误处理
  • 优化内存使用
  • 增强 CSS 模块支持
  • 改进 HMR 更新的分块算法
  • 提升 HMR 源映射可靠性

感谢 Evan You 和 Vite 社区的反馈与贡献,确保 Turbopack 基准测试尽可能准确。我们与 Vite 团队合作验证最新 Turbopack 基准测试,并对测试方法进行了多项改进。

通过这次合作,我们现在使用包含 React 更新机制耗时在内的更准确指标。Turbopack 和 Next.js 13.1 的 webpack 版本中 React Fast Refresh 时间都缩短了 30ms。我们还新增了使用 SWC 的 Vite 基准测试,显示其性能优于默认使用 Babel 的 Vite。查看更新后的基准测试或阅读测试方法

立即在 Next.js 13 中通过 next dev --turbo 试用 Turbopack alpha 版。如有反馈请参与 GitHub 讨论

Next.js 高级中间件

基于社区反馈,我们使 Next.js 中间件比以往更强大。13.1 版本中,现在可以从中间件返回响应,并设置请求头。

这些 API 改进为定制 Next.js 路由生命周期的每个环节提供了强大灵活性。next.config.js 中的 experimental.allowMiddlewareResponseBody 配置选项不再需要。

现在可以更轻松地设置请求头,以及直接响应而无需 rewriteredirect

middleware.ts
import { NextResponse } from 'next/server';
 
export function middleware(request: Request) {
  // 检查用户权限...
  if (!isAuthorized(request)) {
    return NextResponse.json({ message: 'Unauthorized' });
  }
 
  // 添加新请求头,这将改变传入的请求头
  // 可在 getServerSideProps 和 API 路由中读取
  const requestHeaders = new Headers(request.headers);
  requestHeaders.set('x-version', '13.1');
 
  return NextResponse.next({
    request: {
      // 应用新请求头
      headers: requestHeaders,
    },
  });
}

了解更多关于 Next.js 高级中间件的内容。

其他改进

  • @next/font 现在支持在同一字体声明中添加多个字重和样式。了解更多
  • next/dynamic 现在使用 React 原语 lazy()<Suspense>,不再需要之前的 suspense 选项。这些改动使 next/dynamic 兼容 app 目录
  • create-next-app 更新了新设计,默认包含 @next/font 以实现零布局偏移的自动自托管字体。通过 npx create-next-app@latest 试用或部署模板
  • 我们对 App 目录演示站 进行了多项改进,展示 Next.js 13 中 app 目录(测试版)的最新特性和约定。部署你的版本
  • 我们创建了高性能图片库模板,包含图片占位符、懒加载、自动优化、键盘支持等特性。部署你的版本
  • 我们创建了资源指南,详解如何将大型开源 React 和 Express.js 应用迁移至 Next.js,包含详细步骤和特定提交链接

社区

Next.js 是超过 2,400 名独立开发者、Google 和 Meta 等行业合作伙伴以及 Vercel 核心团队共同协作的成果。凭借每周超过 360 万 npm 下载量和 97,900+ GitHub star,Next.js 已成为构建 Web 的最流行方式之一。

加入 GitHub DiscussionsRedditDiscord 上的社区。

本版本由以下成员共同打造:

以及以下贡献者:@aarnadlr, @aaronbrown-vercel, @aaronjy, @abayomi185, @ademilter, @adictonator, @adilansari, @adtc, @alantoa, @aleksa-codes, @alfred-mountfield, @alpha-xek, @andarist, @andykenward, @anujssstw, @artdevgame, @artechventure, @arturbien, @aziyatali, @bennettdams, @bertho-zero, @blue-devil1134, @bot08, @brkalow, @brvnonascimento, @chanceaclark, @chibicode, @chrisipanaque, @chunsch, @colinking, @craigwheeler, @ctjlewis, @cvolant, @danmindru, @davidnx, @delbaoliveira, @devvspaces, @dtinth, @ducanhgh, @duncanogle, @ethomson, @fantaasm, @feugy, @fomichroman, @gruz0, @haschikeks, @hughlilly, @idoob, @iiegor, @imranbarbhuiya, @ingovals, @inokawa, @ishaqibrahimbot, @ismaelrumzan, @jakemstar, @janicklas-ralph, @jaredpalmer, @jaykch, @jimcresswell, @joliss, @josephcsoti, @joshuaslate, @joulev, @jueungrace, @juliusmarminge, @karlhorky, @kikobeats, @kleintorres, @koenpunt, @koltong, @kosai106, @labyrinthitis, @lachlanjc, @laityned, @leerob, @leoortizz, @lorenzobloedow, @lucasassisrosa, @m7yue, @manovotny, @marcus-rise, @matthew-heath, @mattpr, @maxleiter, @maxproske, @meenie, @mmaaaaz, @mnajdova, @moetazaneta, @mrkldshv, @nathanhammond, @nekochantaiwan, @nfinished, @niedziolkamichal, @nocell, @notrab, @nuta, @nutlope, @obusk, @orionmiz, @peraltafederico, @reshmi-sriram, @reyrodrigez, @rightones, @rishabhpoddar, @saseungmin, @serkanbektas, @sferadev, @silvioprog, @sivtu, @soonoo, @sqve, @steven-tey, @sukkaw, @superbahbi, @teobler, @theevilhead, @thomasballinger, @timeyoutakeit, @valentinh, @ws-jm, @wxh06, @yasath, @yutsuten, 和 @zekicaneksi。