Next.js 13.3 新增了社区呼声最高的功能,包括:
- 基于文件的元数据 API:动态生成站点地图、robots.txt、网站图标等
- 动态 Open Graph 图片生成:使用 JSX、HTML 和 CSS 生成 OG 图片
- 应用路由器的静态导出:为服务端组件提供静态/单页应用 (SPA) 支持
- 并行路由与拦截路由:应用路由器的高级路由功能
立即通过以下命令更新:
npm i next@latest react@latest react-dom@latest eslint-config-next@latest
我们即将在下一个小版本中将应用路由器标记为稳定版,目前正集中精力优化性能、改进行为并修复错误。
虽然我们仍在开发如 Mutations 等少量功能,但这些不会影响应用路由器其他功能的 API 接口。我们期待看到您使用应用路由器构建的作品,并欢迎提供反馈。
基于文件的元数据 API
在 Next.js 13.2 中,我们发布了新的元数据 API,允许您通过从布局或页面导出 Metadata 对象来定义元数据(例如 HTML head
元素中的 title
、meta
和 link
标签)。
// 静态元数据
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
文件。
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/og 和 Satori,这些库允许您使用 JSX、HTML 和 CSS 动态生成图片。
@vercel/og
在 Next.js Conf 中接受了考验,为每位参会者生成了超过 10 万张动态票务图片。自发布以来,Vercel 客户广泛采用该功能,下载量超过 90 万次,我们很高兴能将动态图片生成功能带给所有 Next.js 应用,而无需额外安装包。
您现在可以从 next/server
导入 ImageResponse
来生成图片:
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 代码,减少包大小并实现更快的页面加载。
/**
* @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:
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 的模态框路由。
这解决了创建模态框时可能遇到的挑战,例如通过 URL 共享模态框内容、防止刷新页面时丢失上下文,以及通过后退和前进导航关闭和重新打开模态框。
其他改进
- 设计更新: Next.js 首页 和 展示案例 采用了新设计。
- Turbopack: 添加了对中间件、所有
next/font
选项以及服务端组件流式传输的支持,接近测试版(查看演示)。我们还在成熟的 Next.js 应用(如 vercel.com 和 nextjs.org)上修复了更多发现的错误。了解更多。 next.config.js
的快速刷新: 更改next.config.js
现在会自动重新启动本地开发服务器。这扩展了.env
、.env.*
、jsconfig.json
、tsconfig.json
配置文件的自动重新加载。- 无障碍访问: 应用路由器现在包含来自
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"
属性。 - 元数据: 之前用于元数据的 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 Discussions、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 和 @gustavostz。