cover image
📦

Next.js 13.3 (翻译)

next.jsreactssr翻译

Friday, April 7, 2023

Next.js 13.3增加了受欢迎的社区请求功能,包括:
基于文件的元数据API:动态生成站点地图,机器人,收藏夹图标等等。
动态开放图像:使用JSX,HTML和CSS生成OG图像。
应用路由器的静态导出:服务器组件的静态/单页应用程序(SPA)支持。
并行路由和拦截:应用路由器的高级路由功能。
通过运行以下命令更新:

bash

npm i next@latest react@latest react-dom@latest eslint-config-next@latest
我们即将在下一个小版本发布中将App Router标记为稳定版本,并将重点转向优化性能、增强功能和修复错误。
虽然我们仍在开发一些功能,比如变异,但我们不希望这些功能影响其他App Router功能的API表面。我们很期待看到您使用App Router构建的应用,并期待您的反馈(https://github.com/vercel/next.js/discussions/41745)。
基于文件的元数据API
Next.js 13.2中,我们宣布了一个新的元数据API,允许您通过从布局或页面导出元数据对象来定义元数据(例如在HTML的head元素中定义的title、meta和link标签)。

typescript

// layout.js or page.js

// 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](http://params.id/));
return { title: product.title };
}
// Output:
// <head>
//   <title>My Unique Product</title>
// </head>

export default function Page() {}
除了基于配置的元数据之外,元数据API现在还支持新的文件约定,允许您方便地定制页面以改善SEO和Web共享:
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)
例如,您可以使用基于文件的元数据为您的应用程序添加一个favicon和一个用于您的页面的开放图像:/about

typescript

app
├── favicon.ico
├── layout.js
├── page.js
└── about
			├── opengraph-image.jpg
			└── page.js
Next.js将自动为这些文件提供哈希(用于文件名)以进行缓存,并更新相关head元素,包括正确的元数据信息,例如资产的URL、文件类型和图像大小

typescript

// 访问 "/"
<link rel="icon" href="<computedUrl>"/>

// 访问 "/about"
<link rel="icon" href="<computedUrl>"/>
<meta property="og:image" content="<computedUrl>" type="<computedType>" ... />
将静态文件添加到应用程序通常是最简单的方法,但有些情况下您可能需要动态创建文件。对于每个静态文件约定,都有一个相应的动态(.js|.jsx|.ts|.tsx)变体,允许您编写代码来生成文件。
例如,虽然您可以添加一个静态的sitemap.xml文件,但大多数站点都有一些使用外部数据源动态生成的页面。要生成动态站点地图,您可以添加一个返回动态路由数组的sitemap.js文件。

typescript

// 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目录。了解更多关于file-based metadata和API参考的信息。
六个月前,我们发布了@vercel/ogSatori,这些库允许您使用JSX、HTML和CSS动态生成图像。
@vercel/og在Next.js Conf上进行了测试,为每个参与者生成了超过100,000个动态门票图像。自发布以来,在Vercel客户中广泛采用,并已经下载了超过900,000次,我们很高兴为所有Next.js应用程序提供动态生成的图像,无需使用外部包。
现在,您可以从next/server导入ImageResponse来生成图像:

typescript

// /app/about/opengraph-image.tsx
import { ImageResponse } from 'next/server';

export const size = { width: 1200, height: 600 };
export const alt = 'About Acme';
export const contentType = 'image/png';

export default function og() {
  return new ImageResponse();
  // ...
}
ImageResponse自然地与其他Next.js API集成,包括路由处理程序和基于文件的元数据。例如,您可以在opengraph-image.tsx文件中使用ImageResponse来在构建时或在请求时动态生成Open Graph和Twitter图像。
了解更多关于Image Response API的信息。
Next.js App Router现在支持完全静态导出。
您可以作为静态站点或单页应用程序(SPA)开始,然后随后选择升级以使用需要服务器的Next.js功能。
在运行next build时,Next.js会为每个路由生成一个HTML文件。通过将严格的SPA拆分为单独的HTML文件,Next.js可以避免在客户端加载不必要的JavaScript代码,从而减小了捆绑大小并实现更快的页面加载。

typescript

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

module.exports = nextConfig;
静态导出与app路由器的新功能一起工作,包括静态路由处理程序、开放图像以及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引入了新的动态约定,允许您实现高级路由用例:并行路由和拦截路由。这些功能使您能够在同一视图中显示多个页面,例如复杂的仪表板或模态框。
使用Parallel Routes,您可以在同一视图中同时呈现一个或多个页面,这些页面可以独立导航。它还可以用于有条件地呈现页面。
使用命名为“slots”的Parallel Routes。可以使用@folder约定定义插槽:

plain text

dashboard
├── @user
│   └── page.js
├── @team
│   └── page.js
├── layout.js
└── page.js
The layout in the same route segment accepts the slots as props:

typescript

// 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。当保持当前页面的上下文很重要时,例如通过模态框展开提要中的照片,而将提要保持在模态框的后台时,这非常有用。
可以使用 (..) 约定来定义拦截路由,类似于相对路径 ../。您也可以使用 (...) 约定来创建相对于 app 目录的路径。

plain text

feed
├── @modal
│   └── (..)photo
│       └── [id]
│           └── page.tsx
├── page.tsx
└── layout.tsx
photo
└── [id]
    └── page.tsx
在上面的示例中,从用户资料中单击照片将在客户端导航期间在模态中打开照片。但是,刷新或共享页面将使用其默认布局加载照片。
image
这解决了创建模态时可能遇到的挑战,例如使模态内容可通过 URL 共享,防止在刷新页面时丢失上下文以及使用向后和向前导航关闭和重新打开模态。
有关更多示例和行为,请参见ParallelIntercepting Routes documentation
设计更新: Next.js 主页 和 展示 已经以新的设计进行了刷新。
Turbopack: 添加了对中间件、所有 next/font 选项以及流式服务器组件的支持,因为它接近 beta(查看演示)。我们还修补了在成熟的 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 动词之一 (支持的 HTTP 动词) 会在 route.ts 中抛出一个有用的错误。了解更多关于路由处理程序
图片: next/image 现在支持 [fetchPriority="high"] 属性。
元数据: 元数据的先前 API(head.js)在 13.2 中已被弃用。相反,请使用内置的 SEO 支持通过 Metadata API。
将文件夹从路由中排除:_ 为前缀的文件夹将被排除在路由之外,以及任何子段。例如,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)正确恢复依赖于参数的内容。