跳至内容
返回博客

2022年10月25日,星期二

Next.js 13

发布者

正如我们在Next.js Conf上宣布的那样,Next.js 13(稳定版)奠定了在无限制的情况下实现动态化的基础

Next.js 13 和 pages 目录是稳定的,可以用于生产环境。通过运行以下命令立即更新

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

新的 app 目录(测试版)

今天,我们正在改进 Next.js 中的路由和布局体验,并通过引入app目录与 React 的未来保持一致。这是我们之前发布的布局 RFC(用于收集社区反馈)的后续行动。

app目录目前处于测试阶段,我们不建议在生产环境中使用它。您可以使用带有pages目录的 Next.js 13,它包含稳定的功能,例如改进的next/imagenext/link组件,并可以根据自己的节奏选择使用app目录。在可预见的未来,pages目录将继续得到支持。

app目录包含对以下内容的支持:

  • 布局:轻松地在路由之间共享 UI,同时保留状态并避免昂贵的重新渲染。
  • 服务器组件:使服务器优先成为最动态应用程序的默认选项。
  • 流式传输:显示即时加载状态,并在 UI 渲染时以 UI 单位进行流式传输。
  • 数据获取支持:async服务器组件和扩展的fetch API 支持组件级获取。
The app directory can be incrementally adopted from your existing pages/ directory.
可以从现有的 pages/ 目录逐步采用 app 目录。

布局

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

The app/ directory can be incrementally adopted from your existing pages/ directory.
可以从现有的 pages/ 目录逐步采用 app/ 目录。

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

app/page.js
// This file maps to the index route (/)
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 中的服务器组件和嵌套布局,您可以立即渲染不需要数据的页面部分,并为正在获取数据的页面部分显示加载状态。通过这种方法,用户无需等待整个页面加载即可开始与之交互。

You can colocate your application code, such as components, tests, and styles, with your routes.
您可以将应用程序代码(例如组件、测试和样式)与路由放在一起。

部署到 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/...');
  // The return value is *not* serialized
  // You can return Date, Map, Set, etc.
  return res.json();
}
 
// This is an async Server Component
export default async function Page() {
  const data = await getData();
 
  return <main>{/* ... */}</main>;
}

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

// This request should be cached until manually invalidated.
// Similar to `getStaticProps`.
// `force-cache` is the default and can be omitted.
fetch(URL, { cache: 'force-cache' });
 
// This request should be refetched on every request.
// Similar to `getServerSideProps`.
fetch(URL, { cache: 'no-store' });
 
// This request should be cached with a lifetime of 10 seconds.
// Similar to `getStaticProps` with the `revalidate` option.
fetch(URL, { next: { revalidate: 10 } });

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

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

With the app/ directory, you can use a new special file loading.js to automatically create Instant Loading UI with Suspense boundaries.
使用 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 is our Rust-based successor to Webpack, with 700x faster HMR for large applications.
Turbopack 是我们基于 Rust 的 Webpack 继任者,对于大型应用程序,其 HMR 速度提高了 700 倍。

Turbopack仅捆绑开发所需的最小资产,因此启动时间非常快。在一个包含 3000 个模块的应用程序中,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 引入了一个**强大的新图片组件**,使您可以轻松地显示图片,避免布局偏移,并根据需要优化文件以提高性能。

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

新的图片组件

  • 减少客户端 JavaScript 代码
  • 更易于样式化和配置
  • 更易访问,默认情况下需要 `alt` 标签
  • 与 Web 平台保持一致
  • 更快,因为原生懒加载不需要水合
app/page.js
import Image from 'next/image';
import avatar from './lee.png';
 
export default function Home() {
  // "alt" is now required for improved accessibility
  // optional: image files can be colocated inside the app/ directory
  return <Image alt="leeerob" src={avatar} placeholder="blur" />;
}

了解有关图片组件的更多信息部署示例以试用

next/image 升级到 Next.js 13

旧的图片组件已重命名为 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 不再需要手动添加 `` 作为子元素。

这在 12.2 中作为实验性选项添加,现在是默认行为。在 Next.js 13 中,`` 始终渲染 `` 并允许您将属性转发到底层标签。例如

import Link from 'next/link'
 
// Next.js 12: `<a>` has to be nested otherwise it's excluded
<Link href="/about">
  <a>About</a>
</Link>
 
// Next.js 13: `<Link>` always renders `<a>`
<Link href="/about">
  About
</Link>

了解有关改进的链接组件的更多信息部署示例以试用

为了将您的链接升级到 Next.js 13,我们提供了一个代码转换工具,它会自动更新您的代码库。例如,当从根目录运行时,此命令将在您的 ./pages 目录上运行代码转换工具

终端
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>
    ),
  );
}

这种方法比现有解决方案**快 5 倍**,因为它使用了 Vercel 边缘函数、WebAssembly 和一个全新的核心库来将 HTML 和 CSS 转换为图片,并利用 React 组件抽象。

了解有关 OG 图片生成的更多信息部署示例以试用

中间件 API 更新

在 Next.js 12 中,我们引入了中间件以使 Next.js 路由器具有完全的灵活性。我们已经听取了您对初始 API 设计的反馈,并添加了一些改进开发者体验和添加强大新功能的补充。

您现在可以更轻松地设置请求的头部信息

middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
 
export function middleware(request: NextRequest) {
  // Clone the request headers and set a new header `x-version`
  const requestHeaders = new Headers(request.headers);
  requestHeaders.set('x-version', '13');
 
  // You can also set request headers in NextResponse.rewrite
  const response = NextResponse.next({
    request: {
      // New request headers
      headers: requestHeaders,
    },
  });
 
  // Set a new response header `x-version`
  response.headers.set('x-version', '13');
  return response;
}

您现在还可以直接从中间件提供响应,而无需 `rewrite` 或 `redirect`。

middleware.ts
import { NextRequest, NextResponse } from 'next/server';
import { isAuthenticated } from '@lib/auth';
 
// Limit the middleware to paths starting with `/api/`
export const config = {
  matcher: '/api/:function*',
};
 
export function middleware(request: NextRequest) {
  // Call our authentication function to check the request
  if (!isAuthenticated(request)) {
    // Respond with JSON indicating an error message
    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 的子元素不再可以是 ``。添加 `legacyBehavior` 属性以使用旧行为,或删除 `` 以进行升级。一个 代码转换工具可用 用于自动升级您的代码。
  • 当 `User-Agent` 是机器人时,路由不再预取。
  • 已删除 `next.config.js` 中已弃用的 `target` 选项。

  • 已更改支持的浏览器,不再支持 Internet Explorer,而是面向现代浏览器。您仍然可以使用 Browserslist 更改目标浏览器。
    • Chrome 64+
    • Edge 79+
    • Firefox 67+
    • Opera 51+
    • Safari 12+

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

社区

六年前,我们向公众发布了 Next.js。我们的目标是构建一个零配置的 React 框架,简化您的开发体验。回顾过去,看到社区的成长以及我们一起取得的成就令人难以置信。让我们继续前行。

Next.js 是超过 2400 位开发人员、Google 和 Meta 等行业合作伙伴以及我们核心团队共同努力的结果。Next.js 每周拥有超过 300 万次 npm 下载量和 94,000 个 GitHub 星标,是构建 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。