Back返回博客

Next.js 13.3 版本发布

Next.js 13.3 引入了动态 Open Graph 图片生成、高级静态导出、并行路由与拦截路由、OpenTelemetry 支持等新特性。

Next.js 13.3 新增了社区呼声最高的功能,包括:

立即通过以下命令更新:

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

我们即将在下一个小版本中将应用路由器标记为稳定版,目前正集中精力优化性能、改进行为并修复错误。

虽然我们仍在开发如 Mutations 等少量功能,但这些不会影响应用路由器其他功能的 API 接口。我们期待看到您使用应用路由器构建的作品,并欢迎提供反馈

基于文件的元数据 API

Next.js 13.2 中,我们发布了新的元数据 API,允许您通过从布局或页面导出 Metadata 对象来定义元数据(例如 HTML head 元素中的 titlemetalink 标签)。

layout.js 或 page.js
// 静态元数据
export const metadata = {
  title: '首页',
};
// 输出:
// <head>
//	 <title>首页</title>
// </head>
 
// 或动态元数据
export async function generateMetadata({ params, searchParams }) {
  const product = await getProduct(params.id);
  return { title: product.title };
}
// 输出:
// <head>
//	 <title>我的独特产品</title>
// </head>
 
export default function Page() {}

除了基于配置的元数据外,元数据 API 现在支持新的文件约定,让您可以方便地定制页面以提升 SEO 和网页分享效果:

  • opengraph-image.(jpg|png|svg)
  • twitter-image.(jpg|png|svg)
  • favicon.ico
  • icon.(ico|jpg|png|svg)
  • sitemap.(xml|js|jsx|ts|tsx)
  • robots.(txt|js|jsx|ts|tsx)
  • manifest.(json|js|jsx|ts|tsx)

例如,您可以使用基于文件的元数据为应用添加网站图标,并为 /about 页面添加 Open Graph 图片:

app
├── favicon.ico
├── layout.js
├── page.js
└── about
    ├── opengraph-image.jpg
    └── page.js

Next.js 将在生产环境中自动为这些文件添加哈希值(用于文件名)以便缓存,并更新相关 head 元素中的元数据信息,如资源 URL、文件类型和图片尺寸。

// 访问 "/"
<link rel="icon" href="<计算后的URL>"/>
 
// 访问 "/about"
<link rel="icon" href="<计算后的URL>"/>
<meta property="og:image" content="<计算后的URL>" type="<计算后的类型>" ... />

向应用添加静态文件通常是最简单的方法,但在某些情况下您可能需要动态创建文件。对于每个静态文件约定,都有一个对应的动态 (.js|.jsx|.ts|.tsx) 变体,允许您编写代码来生成文件。

例如,虽然您可以添加静态的 sitemap.xml 文件,但大多数网站的某些页面是使用外部数据源动态生成的。要生成动态站点地图,您可以添加一个返回动态路由数组的 sitemap.js 文件。

app/sitemap.js
export default async function sitemap() {
  const res = await fetch('https://.../posts');
  const allPosts = await res.json();
 
  const posts = allPosts.map((post) => ({
    url: `https://acme.com/blog/${post.slug}`,
    lastModified: post.publishedAt,
  }));
 
  const routes = ['', '/about', '/blog'].map((route) => ({
    url: `https://acme.com${route}`,
    lastModified: new Date().toISOString(),
  }));
 
  return [...routes, ...posts];
}

通过基于配置和新的基于文件的选项,您现在拥有了一个全面的元数据 API,涵盖静态和动态元数据。

元数据 API 在 13.3 版本中适用于应用路由器 (app),不适用于 pages 目录。了解更多关于基于文件的元数据并查看 API 参考

动态 Open Graph 图片生成

六个月前,我们发布了 @vercel/ogSatori,这些库允许您使用 JSX、HTML 和 CSS 动态生成图片。

@vercel/ogNext.js Conf 中接受了考验,为每位参会者生成了超过 10 万张动态票务图片。自发布以来,Vercel 客户广泛采用该功能,下载量超过 90 万次,我们很高兴能将动态图片生成功能带给所有 Next.js 应用,而无需额外安装包。

您现在可以从 next/server 导入 ImageResponse 来生成图片:

/app/about/opengraph-image.tsx
import { ImageResponse } from 'next/server';
 
export const size = { width: 1200, height: 600 };
export const alt = '关于 Acme';
export const contentType = 'image/png';
export const runtime = 'edge';
 
export default function og() {
  return new ImageResponse();
  // ...
}

ImageResponse 自然与其他 Next.js API 良好集成,包括路由处理程序和基于文件的元数据。例如,您可以在 opengraph-image.tsx 文件中使用 ImageResponse,在构建时或请求时动态生成 Open Graph 和 Twitter 图片。

了解更多关于 图片响应 API

应用路由器的静态导出

Next.js 应用路由器现在支持完全静态导出。

您可以先作为静态站点或单页应用 (SPA) 开始,然后根据需要升级使用需要服务器的 Next.js 功能。

运行 next build 时,Next.js 会为每个路由生成一个 HTML 文件。通过将严格的 SPA 拆分为单独的 HTML 文件,Next.js 可以避免在客户端加载不必要的 JavaScript 代码,减少包大小并实现更快的页面加载。

next.config.js
/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  output: 'export',
};
 
module.exports = nextConfig;

静态导出与应用路由器的新功能兼容,包括静态路由处理程序、Open Graph 图片和 React 服务端组件。

例如,服务端组件将在构建期间运行,类似于传统的静态站点生成,将组件渲染为初始页面加载的静态 HTML 和客户端路由导航之间的静态有效负载。

以前,要在 pages 目录中使用静态导出,您需要运行 next export。然而,通过 next.config.js 选项,当设置 output: 'export' 时,next build 将输出一个 out 目录。您可以为应用路由器和 pages 目录使用相同的配置。这意味着不再需要 next export

借助高级静态导出支持,您将在开发过程 (next dev) 中更早地收到错误,例如尝试使用需要服务器的动态函数(如 cookies()headers())。

了解更多关于 静态导出

并行路由与拦截路由

Next.js 13.3 引入了新的动态约定,允许您实现高级路由场景:并行路由和拦截路由。这些功能使您能够在同一视图中显示多个页面,如复杂的仪表板或模态框。

通过并行路由,您可以在同一视图中同时渲染一个或多个可以独立导航的页面。它还可以用于有条件地渲染页面。

并行路由使用名为**"插槽"**的约定创建。插槽通过 @folder 约定定义:

dashboard
├── @user
│   └── page.js
├── @team
│   └── page.js
├── layout.js
└── page.js

同一路由段中的布局接受插槽作为 props:

app/dashboard/layout.js
export default async function Layout({ children, user, team }) {
  const userType = getCurrentUserType();
 
  return (
    <>
      {userType === 'user' ? user : team}
      {children}
    </>
  );
}

在上面的示例中,@user@team 并行路由插槽(显式)根据您的逻辑有条件地渲染。children 是一个隐式路由插槽,不需要映射到 @folder。例如,dashboard/page.js 等同于 dashboard/@children/page.js

拦截路由允许您在当前布局中加载一个新路由,同时"屏蔽"浏览器 URL。这在保持当前页面上下文很重要时非常有用,例如通过模态框展开 feed 中的照片,其中 feed 保持在模态框的背景中。

拦截路由可以使用 (..) 约定定义,类似于相对路径 ../。您还可以使用 (...) 约定创建相对于 app 目录的路径。

feed
├── @modal
│   └── (..)photo
│       └── [id]
│           └── page.tsx
├── page.tsx
└── layout.tsx
photo
└── [id]
    └── page.tsx

在上面的示例中,从用户个人资料点击照片将在客户端导航期间在模态框中打开照片。然而,刷新或分享页面将使用默认布局加载照片。

并行路由和拦截路由实现了类似 Instagram 的模态框路由

并行路由和拦截路由实现了类似 Instagram 的模态框路由。

这解决了创建模态框时可能遇到的挑战,例如通过 URL 共享模态框内容、防止刷新页面时丢失上下文,以及通过后退和前进导航关闭和重新打开模态框。

更多示例和行为,请参阅 并行路由拦截路由文档

其他改进

  • 设计更新: Next.js 首页展示案例 采用了新设计。
  • Turbopack: 添加了对中间件、所有 next/font 选项以及服务端组件流式传输的支持,接近测试版(查看演示)。我们还在成熟的 Next.js 应用(如 vercel.comnextjs.org)上修复了更多发现的错误。了解更多
  • next.config.js 的快速刷新: 更改 next.config.js 现在会自动重新启动本地开发服务器。这扩展了 .env.env.*jsconfig.jsontsconfig.json 配置文件的自动重新加载。
  • 无障碍访问: 应用路由器现在包含来自 pages 的路由公告。此功能向屏幕阅读器和其他辅助技术宣布客户端路由转换。了解更多
  • 静态类型链接: next.config.js 中设置的 redirectsrewrites 现在在类型检查期间被考虑。了解更多
  • create-next-app 的 Tailwind CSS: 使用 npx create-next-app@latest 启动新项目时,您现在可以选择 Tailwind CSS 或使用 --tailwind 标志,以预先配置您的应用使用此样式解决方案。
  • 路由处理程序: 使用 export default 而不是 支持的 HTTP 动词 现在会抛出有用的错误与 route.ts了解更多关于路由处理程序
  • 图片: next/image 现在支持 fetchPriority="high" 属性。
  • 元数据: 之前用于元数据的 API (head.js),在 13.2 中已弃用,现已被移除。相反,使用通过 元数据 API 内置的 SEO 支持。
  • 选择退出路由的文件夹: 在文件夹前加上 _ 以使其和任何子段退出路由。例如,app/_dashboard/page.tsx 将不可路由。
  • 应用路由器: 我们添加了一个新的 useParams 客户端组件钩子,用于读取给定路由段的动态参数。了解更多
  • 改进的样式表加载: Next.js 现在实现了 React 的 Suspensey CSS,修复了许多关于 CSS 加载和无样式内容闪烁的问题,特别是在导航期间。
  • 改进的未找到处理: 除了捕获预期的 notFound() 错误外,根 app/not-found.js 文件还将处理应用中任何未匹配的 URL。这意味着访问应用中未处理的 URL 的用户将看到由 app/not-found.js 文件导出的 UI。了解更多
  • 改进的客户端路由器缓存: router.refresh() 现在将使整个缓存失效,并且搜索参数现在是缓存键的一部分,允许在两个搜索参数之间导航(例如 /?search=leerob/?search=tim)以正确恢复依赖于参数的内容。

社区

Next.js 是超过 2,600 名独立开发者、Google 和 Meta 等行业合作伙伴以及 Vercel 核心团队共同努力的结果。每周超过 420 万次 npm 下载和 104,000+ GitHub 星标,Next.js 是构建 Web 的最流行方式之一。

加入 GitHub DiscussionsRedditDiscord 上的社区。

此版本由以下人员共同打造:

以及以下贡献者:@shuding、@huozhi、@sokra、@hanneslund、@JesseKoldewijn、@kaguya3222、@yangshun、@ijjk、@konomae、@Brooooooklyn、@jridgewell、@zlrlyy、@JohnDaly、@abhiyandhakal、@benjie、@johnnyomair、@nk980113、@dirheimerb、@DerTimonius、@DuCanhGH、@padmaia、@stafyniaksacha、@Gladowar、@zek、@jankaifer、@styfle、@balazsorban44、@wbinnssmith、@chibicode、@ForsakenHarmony、@franktronics、@FSaldanha、@Schniz、@raisedadead、@AdamKatzDev、@wyattjoh、@leerob、@meesvandongen、@vladikoff、@feedthejim、@tka5、@pyjun01、@gdborton、@M3kH、@aretrace、@shivanshubisht、@alexkirsz、@agrattan0820、@vinaykulk621、@heyitsuzair、@mrkldshv、@timneutkens、@furkanmavili、@swaminator、@EndangeredMassa、@DevEsteves、@rishabhpoddar、@schehata、@molebox、@dlehmhus、@akshaynox、@sp00ls、@janicklas-ralph、@tomryanx、@kwonoj、@karlhorky、@kdy1、@dante-robinson、@lachlanjc、@ianmacartney、@hotters、@isaackatayev、@insik-han、@jayair、@ivanhofer、@javivelasco、@SukkaW、@visshaljagtap、@imranbarbhuiya、@nivak-monarch、@HarshaVardhanReddyDuvvuru、@ianldgs、@ricardofiorani、@swarnava 和 @gustavostz。