2023年4月6日,星期四
Next.js 13.3
发布者Next.js 13.3 添加了社区广受欢迎的功能,包括:
- 基于文件的元数据 API:动态生成站点地图、robots、网站图标等。
- 动态 Open Graph 图像:使用 JSX、HTML 和 CSS 生成 OG 图像。
- App Router 的静态导出:支持服务器组件的静态 / 单页应用程序 (SPA)。
- 并行路由和拦截:App Router 的高级路由功能。
立即通过运行以下命令进行更新:
npm i next@latest react@latest react-dom@latest eslint-config-next@latest我们即将在此次小版本发布中将 App Router 标记为稳定版,并将重点转移到优化性能、增强行为和修复错误上。
虽然我们仍在开发一些功能,如 Mutations,但我们预计这些功能不会影响其他 App Router 功能的 API 接口。我们很高兴看到您使用 App Router 构建了什么,并期待您的反馈。
基于文件的元数据 API
在Next.js 13.2中,我们发布了一个新的元数据 API,允许您通过从布局或页面导出元数据对象来定义元数据(例如 HTML head 元素中的 title、meta 和 link 标签)。
// either Static metadata
export const metadata = {
title: 'Home',
};
// Output:
// <head>
// <title>Home</title>
// </head>
// or Dynamic metadata
export async function generateMetadata({ params, searchParams }) {
const product = await getProduct(params.id);
return { title: product.title };
}
// Output:
// <head>
// <title>My Unique Product</title>
// </head>
export default function Page() {}除了基于配置的元数据,元数据 API 现在支持新的文件约定,让您可以方便地自定义页面,从而改进 SEO 和网络共享
opengraph-image.(jpg|png|svg)twitter-image.(jpg|png|svg)favicon.icoicon.(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.jsNext.js 会自动在生产环境中为这些文件提供哈希(文件名),以便进行缓存,并用正确的元数据信息(如资产 URL、文件类型和图像大小)更新相关的 head 元素。
// Visiting "/"
<link rel="icon" href="<computedUrl>"/>
// Visiting "/about"
<link rel="icon" href="<computedUrl>"/>
<meta property="og:image" content="<computedUrl>" type="<computedType>" ... />将静态文件添加到您的应用程序通常是最简单的方法,但在某些情况下您可能需要动态创建文件。对于每个静态文件约定,都有一个相应的动态 (.js|.jsx|.ts|.tsx) 变体,允许您编写代码来生成文件。
例如,虽然您可以添加静态 sitemap.xml 文件,但大多数网站都有一些使用外部数据源动态生成的页面。要生成动态站点地图,您可以添加一个 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 在 App Router (app) 的 13.3 版本中可用。在 pages 目录中不可用。了解更多关于基于文件的元数据并查看 API 参考。
动态 Open Graph 图像生成
六个月前,我们发布了@vercel/og 和 Satori,这些库允许您使用 JSX、HTML 和 CSS 动态生成图像。
@vercel/og 在Next.js Conf上经过了测试,为每位与会者生成了超过 100,000 张动态票务图像。凭借 Vercel 客户的广泛采用以及发布以来超过 900,000 次下载,我们很高兴能够将动态生成的图像带到所有 Next.js 应用程序中,而无需外部包。
您现在可以从 next/server 导入 ImageResponse 来生成图像。
import { ImageResponse } from 'next/server';
export const size = { width: 1200, height: 600 };
export const alt = 'About Acme';
export const contentType = 'image/png';
export const runtime = 'edge';
export default function og() {
return new ImageResponse();
// ...
}ImageResponse 自然地与其他 Next.js API 良好集成,包括 Route Handlers 和基于文件的元数据。例如,您可以在 opengraph-image.tsx 文件中使用 ImageResponse 在构建时或在请求时动态生成 Open Graph 和 Twitter 图像。
了解更多关于图像响应 API的信息。
App Router 的静态导出
Next.js App Router 现在支持完全静态导出。
您可以从静态网站或单页应用程序 (SPA) 开始,然后选择升级以使用需要服务器的 Next.js 功能。
运行 next build 时,Next.js 会为每个路由生成一个 HTML 文件。通过将严格的 SPA 分解为单独的 HTML 文件,Next.js 可以避免在客户端加载不必要的 JavaScript 代码,从而减小包大小并加快页面加载速度。
/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
output: 'export',
};
module.exports = nextConfig;静态导出与 app 路由的新功能配合使用,包括静态路由处理器、Open Graph 图像和 React 服务器组件。
例如,服务器组件将在构建期间运行,类似于传统的静态网站生成,将组件渲染为初始页面加载的静态 HTML 和客户端在路由之间导航的静态负载。
以前,要在 pages 目录中使用静态导出,您需要运行 next export。但是,使用 next.config.js 选项,当设置 output: 'export' 时,next build 将输出一个 out 目录。您可以将相同的配置用于 app 路由和 pages 目录。这意味着不再需要 next export。
借助高级静态导出支持,您将在开发过程(next dev)中更早地发现错误,例如在尝试使用需要服务器的动态函数(如 cookies() 或 headers())时。
了解更多关于静态导出的信息。
并行路由和拦截
Next.js 13.3 引入了新的动态约定,允许您实现高级路由用例:并行路由和拦截路由。这些功能使您可以在同一视图中显示多个页面,例如复杂的仪表板或模态框。
通过并行路由,您可以在同一视图中同时渲染一个或多个可以独立导航的页面。它还可以用于有条件地渲染页面。
并行路由使用命名“槽位”创建。槽位使用 @folder 约定定义
dashboard
├── @user
│ └── page.js
├── @team
│ └── page.js
├── layout.js
└── page.js同一路由段中的布局将槽位作为 props 接受
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。当保持当前页面的上下文很重要时,这很有用,例如通过模态框展开提要中的照片,其中提要保留在模态框的背景中。
拦截路由可以使用 (..) 约定定义,类似于相对路径 ../。您还可以使用 (...) 约定创建相对于 app 目录的路径。
feed
├── @modal
│ └── (..)photo
│ └── [id]
│ └── page.tsx
├── page.tsx
└── layout.tsx
photo
└── [id]
└── page.tsx在上面的示例中,从用户个人资料中点击照片将在客户端导航期间在模态框中打开照片。但是,刷新或共享页面将以其默认布局加载照片。

这解决了您在创建模态框时可能遇到的挑战,例如通过 URL 使模态框内容可共享,防止在页面刷新时丢失上下文,以及通过前进和后退导航关闭和重新打开模态框。
其他改进
- 设计更新: Next.js 主页和展示页已更新,采用了新设计。
- Turbopack: 添加了对中间件、所有
next/font选项以及与服务器组件流式传输的支持,因为它正接近测试版(请参阅演示)。我们还在对成熟的 Next.js 应用(如 vercel.com和nextjs.org进行内部测试时发现的其他错误进行了修补。了解更多。 next.config.js的快速刷新: 对next.config.js的更改现在将自动重新启动您的本地开发服务器。这扩展了.env、.env.*、jsconfig.json、tsconfig.json配置文件自动重新加载的范围。- 无障碍: App Router 现在包含
pages的路由公告功能。此功能向屏幕阅读器和其他辅助技术公告客户端路由转换。了解更多。 - 静态类型链接:
next.config.js中设置的redirects和rewrites现在在类型检查期间被考虑在内。了解更多。 create-next-app中的 Tailwind CSS: 使用npx create-next-app@latest启动新项目时,您现在可以选择 Tailwind CSS,或使用--tailwind标志,以使用此样式解决方案预配置您的应用程序。- 路由处理器: 使用
export default而不是支持的 HTTP 动词现在会在route.ts中抛出一个有用的错误。了解更多关于路由处理器。 - 图像:
next/image现在支持fetchPriority="high"属性。 - 元数据: 之前已在 13.2 版本中弃用的元数据 API (
head.js) 已被移除。请改用通过 元数据 API 提供的内置 SEO 支持。 - 将文件夹排除在路由之外: 在文件夹名称前加上下划线
_,即可将其及其任何子段排除在路由之外。例如,app/_dashboard/page.tsx将不可路由。 - App Router: 我们添加了一个新的
useParams客户端组件 hook,用于读取给定路由段的动态参数。了解更多。 - 改进的样式表加载: Next.js 现在实现了 React 的 Suspensey CSS,这解决了许多关于 CSS 加载和未样式化内容闪烁的问题,尤其是在导航期间。
- 改进的 Not Found 处理: 除了捕获预期的
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 核心团队共同努力的成果。Next.js 每周 npm 下载量超过 420 万次,GitHub 星标超过 104,000 个,是构建 Web 最流行的方式之一。
加入社区:GitHub 讨论区、Reddit 和 Discord。
此版本由以下人员提供
- Next.js 团队:Andrew、Balazs、Hannes、Jan、Jiachi、Jimmy、JJ、Josh、Sebastian、Shu、Steven、Tim 和 Wyatt。
- Turbopack 团队:Alex、Donny、Justin、Leah、LongYinan、Maia、OJ、Tobias 和 Will。
以及以下贡献:@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, and @gustavostz.