Back返回博客

Next.js 13

Next.js 13 引入了应用目录中的布局 (Layouts)、React 服务端组件 (Server Components) 和流式渲染 (Streaming),以及 Turbopack、改进的图像组件和全新的字体组件。

正如我们在 Next.js 大会上宣布的,Next.js 13(稳定版)为无限动态能力奠定了基础:

Next.js 13 和 pages 目录已稳定并可用于生产环境。立即通过以下命令更新:

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

新版 app 目录(测试版)

今天,我们通过引入 app 目录改进了 Next.js 的路由和布局体验,并与 React 的未来发展方向保持一致。这是对之前发布的布局 RFC 的后续更新,该 RFC 曾征求社区反馈。

app 目录目前处于测试阶段,我们暂不建议在生产环境中使用。您可以在 Next.js 13 中使用稳定的 pages 目录功能(如改进的 next/imagenext/link 组件),并自行决定何时采用 app 目录。pages 目录在可预见的未来将继续得到支持。

app 目录包含以下功能:

  • 布局: 轻松在路由间共享 UI 同时保持状态,避免昂贵的重新渲染。
  • 服务端组件: 为最动态的应用默认采用服务端优先模式。
  • 流式渲染: 显示即时加载状态,并按 UI 单元逐步流式渲染。
  • 数据获取支持: 异步服务端组件和扩展的 fetch API 支持组件级数据获取。

app 目录可以从您现有的 pages/ 目录逐步采用。

app 目录可以从您现有的 pages/ 目录逐步采用。

布局

app/ 目录让您可以轻松布局复杂界面,这些界面能在导航间保持状态、避免昂贵的重新渲染,并支持高级路由模式。此外,您可以嵌套布局,并将应用代码(如组件、测试和样式)与路由放在一起。

app/ 目录可以从您现有的 pages/ 目录逐步采用。

app/ 目录可以从您现有的 pages/ 目录逐步采用。

app/ 中创建路由只需要一个文件 page.js

app/page.js
// 该文件映射到根路由(/)
export default function Page() {
  return <h1>Hello, Next.js!</h1>;
}

然后,您可以通过文件系统定义布局。布局在多个页面间共享 UI。在导航时,布局会保持状态、保持交互性且不会重新渲染。

app/blog/layout.js
export default function BlogLayout({ children }) {
  return <section>{children}</section>;
}

了解更多关于布局和页面的信息部署示例体验

服务端组件

app/ 目录引入了对 React 新的服务端组件架构的支持。服务端组件和客户端组件分别利用服务器和客户端的优势,让您能够构建快速、高度交互的应用,同时提供出色的开发体验。

通过服务端组件,我们为构建复杂界面奠定了基础,同时减少了发送到客户端的 JavaScript 数量,从而实现更快的初始页面加载。

当路由加载时,Next.js 和 React 运行时会随之加载,其大小是可缓存可预测的。该运行时不会随着应用增长而变大。此外,运行时是异步加载的,使得来自服务器的 HTML 可以在客户端逐步增强。

了解更多关于服务端组件的信息部署示例体验

流式渲染

app/ 目录引入了逐步渲染和增量流式渲染 UI 单元到客户端的能力。

借助服务端组件和 Next.js 中的嵌套布局,您可以立即渲染不需要特定数据的页面部分,并为正在获取数据的页面部分显示加载状态。通过这种方式,用户无需等待整个页面加载完成即可开始交互。

您可以将应用代码(如组件、测试和样式)与路由放在一起。

您可以将应用代码(如组件、测试和样式)与路由放在一起。

当部署到 Vercel 时,使用 app/ 目录的 Next.js 13 应用默认会在 Node.js 和 Edge 运行时中流式传输响应,以提高性能。

了解更多关于流式渲染的信息部署示例体验

数据获取

React 最近的Promise 支持 RFC 引入了一种强大的新方式在组件内获取数据和处理 Promise:

app/page.js
async function getData() {
  const res = await fetch('https://api.example.com/...');
  // 返回值不会被序列化
  // 您可以返回 Date、Map、Set 等
  return res.json();
}
 
// 这是一个异步服务端组件
export default async function Page() {
  const data = await getData();
 
  return <main>{/* ... */}</main>;
}

React 和 Next.js 还扩展了原生的 fetch Web API。它会自动去重 fetch 请求,并提供一种灵活的方式来在组件级别获取、缓存和重新验证数据。这意味着静态站点生成 (SSG)、服务端渲染 (SSR) 和增量静态再生 (ISR) 的所有优势现在都可以通过一个 API 获得:

// 此请求应缓存直到手动失效。
// 类似于 `getStaticProps`。
// `force-cache` 是默认值,可以省略。
fetch(URL, { cache: 'force-cache' });
 
// 此请求应在每次请求时重新获取。
// 类似于 `getServerSideProps`。
fetch(URL, { cache: 'no-store' });
 
// 此请求应缓存 10 秒。
// 类似于 `getStaticProps` 的 `revalidate` 选项。
fetch(URL, { next: { revalidate: 10 } });

app 目录中,您可以在布局、页面和组件内获取数据,包括支持从服务器流式传输响应

我们正在提供符合人体工程学的方式来处理加载和错误状态,并在 UI 渲染时流式传输。在未来的版本中,我们还将改进和简化数据变更。

使用 app/ 目录时,您可以使用新的特殊文件 loading.js 自动创建带有 Suspense 边界的即时加载 UI。

使用 app/ 目录时,您可以使用新的特殊文件 loading.js 自动创建带有 Suspense 边界的即时加载 UI。

我们很高兴能与开源社区、包维护者和其他为 React 生态系统做出贡献的公司合作,共同构建 React 和 Next.js 的新时代。能够在组件内共同定位数据获取并向客户端发送更少的 JavaScript 是我们通过 app/ 目录实现的两个重要社区反馈。

了解更多关于数据获取的信息部署示例体验

介绍 Turbopack(Alpha 版)

Next.js 13 包含 Turbopack,这是基于 Rust 的新一代 Webpack 替代品。

Webpack 已被下载超过 30 亿次。虽然它是构建 Web 的重要组成部分,但我们已经达到了基于 JavaScript 的工具所能实现的性能极限。

在 Next.js 12 中,我们开始向原生 Rust 驱动的工具过渡。我们首先从 Babel 迁移,实现了 17 倍的转译速度提升。然后,我们替换了 Terser,实现了 6 倍的压缩速度提升。现在是时候全面采用原生打包工具了。

在 Next.js 13 中使用 Turbopack alpha 版可以实现:

  • 更新速度比 Webpack 快 700 倍
  • 更新速度比 Vite 快 10 倍
  • 冷启动速度比 Webpack 快 4 倍

Turbopack 是我们基于 Rust 的 Webpack 继任者,为大型应用提供 700 倍更快的 HMR。

Turbopack 是我们基于 Rust 的 Webpack 继任者,为大型应用提供 700 倍更快的 HMR。

Turbopack 在开发环境中仅打包所需的最小资源,因此启动时间极快。在一个包含 3,000 个模块的应用中,Turbopack 只需 1.8 秒 启动。Vite 需要 11.4 秒,而 Webpack 需要 16.5 秒

Turbopack 开箱即用地支持服务端组件、TypeScript、JSX、CSS 等。在 alpha 阶段,许多功能尚未支持。我们期待听到您使用 Turbopack 加速本地迭代的反馈。

注意: Next.js 中的 Turbopack 目前仅支持 next dev。查看支持的功能。我们也在努力通过 Turbopack 添加对 next build 的支持。

立即在 Next.js 13 中尝试 Turbopack alpha 版,使用 next dev --turbo

next/image

Next.js 13 引入了强大的新 Image 组件,让您可以轻松显示图像而不会出现布局偏移,并按需优化文件以提高性能。

在 Next.js 社区调查中,70% 的受访者表示他们在生产环境中使用了 Next.js Image 组件,并因此看到了核心 Web 指标的改进。在 Next.js 13 中,我们进一步改进了 next/image

新版 Image 组件:

  • 发送更少的客户端 JavaScript
  • 更易于样式化和配置
  • 默认需要 alt 标签以提高可访问性
  • 与 Web 平台保持一致
  • 速度更快,因为原生懒加载不需要水合
app/page.js
import Image from 'next/image';
import avatar from './lee.png';
 
export default function Home() {
  // 现在 "alt" 是必需的以提高可访问性
  // 可选:图像文件可以放在 app/ 目录内
  return <Image alt="leeerob" src={avatar} placeholder="blur" />;
}

了解更多关于 Image 组件的信息部署示例体验

升级 next/image 至 Next.js 13

旧版 Image 组件已重命名为 next/legacy/image。我们提供了一个代码修改工具,可以自动将您现有的 next/image 用法更新为 next/legacy/image。例如,以下命令会在根目录运行时对您的 ./pages 目录运行代码修改工具:

终端
npx @next/codemod next-image-to-legacy-image ./pages

了解更多关于代码修改工具的信息

@next/font

Next.js 13 引入了全新的字体系统,具有以下特点:

  • 自动优化您的字体,包括自定义字体
  • 移除外部网络请求以提高隐私和性能
  • 内置自动自托管任何字体文件
  • 使用 CSS size-adjust 属性自动实现零布局偏移

这个新字体系统让您可以方便地使用所有 Google 字体,同时兼顾性能和隐私。CSS 和字体文件在构建时下载,并与您的其他静态资源一起自托管。浏览器不会向 Google 发送任何请求。

app/layout.js / pages/_app.js
import { Inter } from '@next/font/google';
 
const inter = Inter();
 
<html className={inter.className}></html>;

还支持自定义字体,包括自动自托管、缓存和预加载字体文件。

app/layout.js / pages/_app.js
import localFont from '@next/font/local';
 
const myFont = localFont({ src: './my-font.woff2' });
 
<html className={myFont.className}></html>;

您可以自定义字体加载体验的每个部分,同时仍确保出色的性能和零布局偏移,包括 font-display、预加载、回退等。

了解更多关于新版字体组件的信息部署示例体验

next/link 不再需要手动添加 <a> 作为子元素。

这一功能在 12.2 版本中作为实验性选项引入,现在已成为默认行为。在 Next.js 13 中,<Link> 始终渲染 <a> 并允许您将属性传递给底层标签。例如:

import Link from 'next/link'
 
// Next.js 12: `<a>` 必须嵌套,否则会被排除
<Link href="/about">
  <a>About</a>
</Link>
 
// Next.js 13: `<Link>` 始终渲染 `<a>`
<Link href="/about">
  About
</Link>

了解更多关于改进的 Link 组件的信息部署示例体验

要将链接升级到 Next.js 13,我们提供了一个代码修改工具 (codemod) 来自动更新您的代码库。例如,以下命令会在项目根目录运行时对 ./pages 目录执行代码修改:

Terminal
npx @next/codemod new-link ./pages

了解更多关于代码修改工具的信息 或查阅相关文档。

OG 图片生成

社交卡片(又称开放图谱图片)能显著提升内容点击率,部分实验显示转化率可提高达 40%。

静态社交卡片耗时、易错且难以维护,因此常常被忽略甚至直接跳过。而需要实时个性化和计算的动态社交卡片至今仍难以实现且成本高昂。

我们推出了全新库 @vercel/og,可与 Next.js 无缝协作生成动态社交卡片。

pages/api/og.jsx
import { ImageResponse } from '@vercel/og';
 
export const config = {
  runtime: 'experimental-edge',
};
 
export default function () {
  return new ImageResponse(
    (
      <div
        style={{
          display: 'flex',
          fontSize: 128,
          background: 'white',
          width: '100%',
          height: '100%',
        }}
      >
        Hello, World!
      </div>
    ),
  );
}

该方法通过使用 Vercel 边缘函数、WebAssembly 以及全新的核心库(将 HTML 和 CSS 转换为图像并利用 React 组件抽象),速度比现有解决方案快 5 倍

了解更多关于 OG 图片生成部署示例体验

中间件 API 更新

在 Next.js 12 中,我们引入了中间件以实现 Next.js 路由器的完全灵活性。根据开发者反馈,我们新增了一些功能以优化开发体验并增强能力。

现在您可以更轻松地设置请求头:

middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
 
export function middleware(request: NextRequest) {
  // 克隆请求头并设置新标头 `x-version`
  const requestHeaders = new Headers(request.headers);
  requestHeaders.set('x-version', '13');
 
  // 也可在 NextResponse.rewrite 中设置请求头
  const response = NextResponse.next({
    request: {
      // 新请求头
      headers: requestHeaders,
    },
  });
 
  // 设置新响应头 `x-version`
  response.headers.set('x-version', '13');
  return response;
}

现在还可以直接从中间件返回响应,无需 rewriteredirect

middleware.ts
import { NextRequest, NextResponse } from 'next/server';
import { isAuthenticated } from '@lib/auth';
 
// 将中间件限制为以 `/api/` 开头的路径
export const config = {
  matcher: '/api/:function*',
};
 
export function middleware(request: NextRequest) {
  // 调用身份验证函数检查请求
  if (!isAuthenticated(request)) {
    // 返回包含错误信息的 JSON 响应
    return NextResponse.json(
      {
        success: false,
        message: 'Auth failed',
      },
      {
        status: 401,
      },
    );
  }
}

目前从中间件发送响应需要在 next.config.js 中配置 experimental.allowMiddlewareResponseBody 选项。

重大变更

  • React 最低版本从 17.0.2 升级至 18.2.0
  • Node.js 最低版本从 12.22.0 升级至 14.6.0(因 12.x 已终止支持)(PR)
  • swcMinify 配置项默认值从 false 改为 true,详见 Next.js 编译器
  • next/image 导入更名为 next/legacy/imagenext/future/image 更名为 next/image提供代码修改工具 自动安全重命名导入
  • next/link 子元素不再支持 <a> 标签。添加 legacyBehavior 属性使用旧行为,或移除 <a> 标签升级。提供代码修改工具 自动升级代码
  • User-Agent 为机器人时不再预取路由
  • 已移除 next.config.js 中废弃的 target 选项
  • 支持的浏览器范围变更:不再支持 Internet Explorer,目标转向现代浏览器。仍可通过 Browserslist 调整目标浏览器:
    • Chrome 64+
    • Edge 79+
    • Firefox 67+
    • Opera 51+
    • Safari 12+

了解更多请查看 升级指南

社区

六年前,我们向公众发布了 Next.js。我们的目标是构建一个零配置的 React 框架,简化开发者体验。回望过去,社区的成长和我们共同实现的成果令人惊叹。让我们继续前进。

Next.js 是 超过 2,400 名开发者、Google 和 Meta 等行业合作伙伴以及核心团队共同努力的成果。每周超过 300 万 npm 下载量和 94,000 GitHub star,使 Next.js 成为构建 Web 最流行的方式之一。

特别感谢 Google Chrome 的 Aurora 团队,他们的基础研究和实验为本次发布奠定了基础。

本次发布的贡献者包括:@ijjk, @huozhi, @HaNdTriX, @iKethavel, @timneutkens, @shuding, @rishabhpoddar, @hanneslund, @balazsorban44, @devknoll, @anthonyshew, @TomerAberbach, @philippbosch, @styfle, @mauriciomutte, @hayitsdavid, @abdennor, @Kikobeats, @cjdunteman, @Mr-Afonso, @kdy1, @jaril, @abdallah-nour, @North15, @feedthejim, @brunocrosier, @Schniz, @sedlukha, @hashlash, @Ethan-Arrowood, @fireairforce, @migueloller, @leerob, @janicklas-ralph, @Trystanr, @atilafassina, @nramkissoon, @kasperadk, @valcosmos, @henriqueholtz, @nip10, @jesstelford, @lorensr, @AviAvinav, @SukkaW, @jaycedotbin, @saurabhburade, @notrab, @kwonoj, @sanruiz, @angeloashmore, @falsepopsky, @fmontes, @Gebov, @UltiRequiem, @p13lgst, @Simek, @mrkldshv, @thomasballinger, @kyliau, @AdarshKonchady, @endymion1818, @pedro757, @perkinsjr, @gnoff, @jridgewell, @silvioprog, @mabels, @nialexsan, @feugy, @jackromo888, @crazyurus, @EarlGeorge, @MariaSolOs, @lforst, @maximbaz, @maxam2017, @teobler, @Nutlope, @sunwoo0706, @WestonThayer, @Brooooooklyn, @Nsttt, @charlypoly, @aprendendofelipe, @sviridoff, @jackton1, @nuta, @Rpaudel379, @marcialca, @MarDi66, @ismaelrumzan, @javivelasco, @eltociear, 和 @hiro0218。