主题
应用路由
¥App Router
本指南将帮助你:
¥This guide will help you:
¥Update your Next.js application from version 12 to version 13
¥Upgrade features that work in both the
pagesand theappdirectories¥Incrementally migrate your existing application from
pagestoapp
升级
¥Upgrading
Node.js 版本
¥Node.js Version
Node.js 的最低版本现在是 v18.17。请参阅 Node.js 文档 了解更多信息。
¥The minimum Node.js version is now v18.17. See the Node.js documentation for more information.
Next.js 版本
¥Next.js Version
要更新到 Next.js 版本 13,请使用你首选的包管理器运行以下命令:
¥To update to Next.js version 13, run the following command using your preferred package manager:
bash
npm install next@latest react@latest react-dom@latestESLint 版本
¥ESLint Version
如果你使用 ESLint,则需要升级 ESLint 版本:
¥If you're using ESLint, you need to upgrade your ESLint version:
bash
npm install -D eslint-config-next@latest需要了解:你可能需要在 VS Code 中重新启动 ESLint 服务器以使 ESLint 更改生效。打开命令面板(Mac 上为
cmd+shift+p;Windows 上为ctrl+shift+p)并搜索ESLint: Restart ESLint Server。¥Good to know: You may need to restart the ESLint server in VS Code for the ESLint changes to take effect. Open the Command Palette (
cmd+shift+pon Mac;ctrl+shift+pon Windows) and search forESLint: Restart ESLint Server.
下一步
¥Next Steps
更新后,请参阅以下部分了解后续步骤:
¥After you've updated, see the following sections for next steps:
升级新功能:帮助你升级到新功能(例如改进的图片和链接组件)的指南。
¥Upgrade new features: A guide to help you upgrade to new features such as the improved Image and Link Components.
从
pages目录迁移到app目录:帮助你从pages目录逐步迁移到app目录的分步指南。¥Migrate from the
pagestoappdirectory: A step-by-step guide to help you incrementally migrate from thepagesto theappdirectory.
升级新功能
¥Upgrading New Features
Next.js 13 引入了具有新功能和约定的新 应用路由。新路由位于 app 目录中,并与 pages 目录共存。
¥Next.js 13 introduced the new App Router with new features and conventions. The new Router is available in the app directory and co-exists with the pages directory.
升级到 Next.js 13 不需要使用 App Router。你可以继续使用 pages 以及在两个目录中均有效的新功能,例如更新的 图片组件、链接组件、脚本组件 和 字体优化。
¥Upgrading to Next.js 13 does not require using the App Router. You can continue using pages with new features that work in both directories, such as the updated Image component, Link component, Script component, and Font optimization.
`
` 组件
¥` Component
Next.js 12 通过临时导入对图片组件进行了新的改进:next/future/image。这些改进包括更少的客户端 JavaScript、更简单的扩展和样式图片方法、更好的可访问性以及原生浏览器延迟加载。
¥Next.js 12 introduced new improvements to the Image Component with a temporary import: next/future/image. These improvements included less client-side JavaScript, easier ways to extend and style images, better accessibility, and native browser lazy loading.
在版本 13 中,此新行为现已成为 next/image 的默认行为。
¥In version 13, this new behavior is now the default for next/image.
有两个代码模块可以帮助你迁移到新的图片组件:
¥There are two codemods to help you migrate to the new Image Component:
next-image-to-legacy-image代码模式:安全自动地将next/image导入重命名为next/legacy/image。现有组件将保持相同的行为。¥
next-image-to-legacy-imagecodemod: Safely and automatically renamesnext/imageimports tonext/legacy/image. Existing components will maintain the same behavior.next-image-experimental代码模式:危险地添加内联样式并删除未使用的属性。这将更改现有组件的行为以匹配新的默认值。要使用此 codemod,你需要先运行next-image-to-legacy-imagecodemod。¥
next-image-experimentalcodemod: Dangerously adds inline styles and removes unused props. This will change the behavior of existing components to match the new defaults. To use this codemod, you need to run thenext-image-to-legacy-imagecodemod first.
<Link> 组件
¥<Link> Component
<Link> 组件 不再需要手动添加 <a> 标签作为子标签。此行为是在 版本 12.2 中作为实验选项添加的,现在是默认行为。在 Next.js 13 中,<Link> 始终渲染 <a> 并允许你将 props 转发到底层标签。
¥The <Link> Component no longer requires manually adding an <a> tag as a child. This behavior was added as an experimental option in version 12.2 and is now the default. In Next.js 13, <Link> always renders <a> and allows you to forward props to the underlying tag.
例如:
¥For example:
要将链接升级到 Next.js 13,你可以使用 new-link 代码模式。
¥To upgrade your links to Next.js 13, you can use the new-link codemod.
<Script> 组件
¥<Script> Component
next/script 的行为已更新以支持 pages 和 app,但需要进行一些更改以确保顺利迁移:
¥The behavior of next/script has been updated to support both pages and app, but some changes need to be made to ensure a smooth migration:
将之前包含在
_document.js中的所有beforeInteractive脚本移至根布局文件 (app/layout.tsx)。¥Move any
beforeInteractivescripts you previously included in_document.jsto the root layout file (app/layout.tsx).实验性的
worker策略尚未在app中运行,并且必须删除或修改用此策略表示的脚本以使用不同的策略(例如lazyOnload)。¥The experimental
workerstrategy does not yet work inappand scripts denoted with this strategy will either have to be removed or modified to use a different strategy (e.g.lazyOnload).onLoad、onReady和onError处理程序在服务器组件中不起作用,因此请确保将它们移至 客户端组件 或完全删除它们。¥
onLoad,onReady, andonErrorhandlers will not work in Server Components so make sure to move them to a Client Component or remove them altogether.
字体优化
¥Font Optimization
此前,Next.js 已帮助你优化字体 内联字体 CSS。版本 13 引入了新的 next/font 模块,使你能够自定义字体加载体验,同时仍然确保出色的性能和隐私。pages 和 app 目录均支持 next/font。
¥Previously, Next.js helped you optimize fonts by inlining font CSS. Version 13 introduces the new next/font module which gives you the ability to customize your font loading experience while still ensuring great performance and privacy. next/font is supported in both the pages and app directories.
虽然 内联 CSS 在 pages 中仍然有效,但在 app 中不起作用。你应该使用 next/font 来代替。
¥While inlining CSS still works in pages, it does not work in app. You should use next/font instead.
请参阅 字体优化 页面以了解如何使用 next/font。
¥See the Font Optimization page to learn how to use next/font.
从 pages 迁移到 app
¥Migrating from pages to app
🎥 观看:了解如何逐步采用 App Router → YouTube(16 分钟)。
¥🎥 Watch: Learn how to incrementally adopt the App Router → YouTube (16 minutes).
迁移到 App Router 可能是第一次使用 Next.js 构建于其之上的 React 功能,例如服务器组件、Suspense 等。当与新的 Next.js 功能(例如 特殊文件 和 layouts)相结合时,迁移意味着需要学习新的概念、思维模型和行为变化。
¥Moving to the App Router may be the first time using React features that Next.js builds on top of such as Server Components, Suspense, and more. When combined with new Next.js features such as special files and layouts, migration means new concepts, mental models, and behavioral changes to learn.
我们建议通过将迁移分解为更小的步骤来降低这些更新的综合复杂性。app 目录特意设计为与 pages 目录同时工作,以允许增量式逐页迁移。
¥We recommend reducing the combined complexity of these updates by breaking down your migration into smaller steps. The app directory is intentionally designed to work simultaneously with the pages directory to allow for incremental page-by-page migration.
app目录支持嵌套路由和布局。了解更多。¥The
appdirectory supports nested routes and layouts. Learn more.使用嵌套文件夹定义路由,并使用特殊的
page.js文件使路由段可公开访问。了解更多。¥Use nested folders to define routes and a special
page.jsfile to make a route segment publicly accessible. Learn more.特殊文件约定 用于为每个路由段创建 UI。最常见的特殊文件是
page.js和layout.js。¥Special file conventions are used to create UI for each route segment. The most common special files are
page.jsandlayout.js.使用
page.js定义路由特有的 UI。¥Use
page.jsto define UI unique to a route.使用
layout.js定义在多个路由之间共享的 UI。¥Use
layout.jsto define UI that is shared across multiple routes..js、.jsx或.tsx文件扩展名可用于特殊文件。¥
.js,.jsx, or.tsxfile extensions can be used for special files.
你可以在
app目录中并置其他文件,例如组件、样式、测试等。了解更多。¥You can colocate other files inside the
appdirectory such as components, styles, tests, and more. Learn more.app中的getServerSideProps和getStaticProps等数据获取函数已被 一个新的 API 替换。getStaticPaths已替换为generateStaticParams。¥Data fetching functions like
getServerSidePropsandgetStaticPropshave been replaced with a new API insideapp.getStaticPathshas been replaced withgenerateStaticParams.pages/_app.js和pages/_document.js已替换为单个app/layout.js根布局。了解更多。¥
pages/_app.jsandpages/_document.jshave been replaced with a singleapp/layout.jsroot layout. Learn more.pages/_error.js已替换为更细粒度的error.js特殊文件。了解更多。¥
pages/_error.jshas been replaced with more granularerror.jsspecial files. Learn more.pages/404.js已替换为not-found.js文件。¥
pages/404.jshas been replaced with thenot-found.jsfile.pages/api/*API 路由已替换为route.js(路由处理程序)特殊文件。¥
pages/api/*API Routes have been replaced with theroute.js(Route Handler) special file.
步骤 1:创建 app 目录
¥Step 1: Creating the app directory
更新到最新的 Next.js 版本(需要 13.4 或更高版本):
¥Update to the latest Next.js version (requires 13.4 or greater):
bash
npm install next@latest然后,在项目的根目录(或 src/ 目录)创建一个新的 app 目录。
¥Then, create a new app directory at the root of your project (or src/ directory).
步骤 2:创建根布局
¥Step 2: Creating a Root Layout
在 app 目录中创建一个新的 app/layout.tsx 文件。这是一个 根布局,将应用于 app 内的所有路由。
¥Create a new app/layout.tsx file inside the app directory. This is a root layout that will apply to all routes inside app.
tsx
export default function RootLayout({
// Layouts must accept a children prop.
// This will be populated with nested layouts or pages
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}app目录必须包含根布局。¥The
appdirectory must include a root layout.根布局必须定义
<html>和<body>标签,因为 Next.js 不会自动创建它们¥The root layout must define
<html>, and<body>tags since Next.js does not automatically create them根布局替换
pages/_app.tsx和pages/_document.tsx文件。¥The root layout replaces the
pages/_app.tsxandpages/_document.tsxfiles..js、.jsx或.tsx扩展名可用于布局文件。¥
.js,.jsx, or.tsxextensions can be used for layout files.
要管理 <head> HTML 元素,你可以使用 内置 SEO 支持:
¥To manage <head> HTML elements, you can use the built-in SEO support:
tsx
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Home',
description: 'Welcome to Next.js',
}迁移 _document.js 和 _app.js
¥Migrating _document.js and _app.js
如果你有现有的 _app 或 _document 文件,你可以将内容(例如全局样式)复制到根布局 (app/layout.tsx)。app/layout.tsx 中的样式不适用于 pages/*。迁移时应保留 _app/_document,以防止 pages/* 路由中断。完全迁移后,你就可以安全地删除它们。
¥If you have an existing _app or _document file, you can copy the contents (e.g. global styles) to the root layout (app/layout.tsx). Styles in app/layout.tsx will not apply to pages/*. You should keep _app/_document while migrating to prevent your pages/* routes from breaking. Once fully migrated, you can then safely delete them.
如果你正在使用任何 React Context 提供程序,则需要将它们移至 客户端组件。
¥If you are using any React Context providers, they will need to be moved to a Client Component.
将 getLayout() 模式迁移到布局(可选)
¥Migrating the getLayout() pattern to Layouts (Optional)
Next.js 建议在 pages 目录中添加 页面组件的属性 以实现每页布局。此模式可以替换为 app 目录中对 嵌套布局 的原生支持。
¥Next.js recommended adding a property to Page components to achieve per-page layouts in the pages directory. This pattern can be replaced with native support for nested layouts in the app directory.
See before and after example
之前
¥Before
之后
¥After
从
pages/dashboard/index.js中删除Page.getLayout属性,并沿着 迁移页面的步骤 到达app目录。¥Remove the
Page.getLayoutproperty frompages/dashboard/index.jsand follow the steps for migrating pages to theappdirectory.将
DashboardLayout的内容移动到新的 客户端组件 中以保留pages目录行为。¥Move the contents of
DashboardLayoutinto a new Client Component to retainpagesdirectory behavior.将
DashboardLayout导入到app目录内的新layout.js文件中。¥Import the
DashboardLayoutinto a newlayout.jsfile inside theappdirectory.你可以逐步将
DashboardLayout.js(客户端组件)的非交互部分移至layout.js(服务器组件),以减少发送到客户端的组件 JavaScript 数量。¥You can incrementally move non-interactive parts of
DashboardLayout.js(Client Component) intolayout.js(Server Component) to reduce the amount of component JavaScript you send to the client.
步骤 3:迁移 next/head
¥Step 3: Migrating next/head
在 pages 目录中,next/head React 组件用于管理 <head> 个 HTML 元素,例如 title 和 meta 。 在 app 目录中,next/head 被替换为新的 内置 SEO 支持。
¥In the pages directory, the next/head React component is used to manage <head> HTML elements such as title and meta . In the app directory, next/head is replaced with the new built-in SEO support.
之前:
¥Before:
tsx
import Head from 'next/head'
export default function Page() {
return (
<>
<Head>
<title>My page title</title>
</Head>
</>
)
}之后:
¥After:
tsx
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'My Page Title',
}
export default function Page() {
return '...'
}步骤 4:迁移页面
¥Step 4: Migrating Pages
app目录 中的页面默认为 服务器组件。这与pages目录不同,其中页面为 客户端组件。¥Pages in the
appdirectory are Server Components by default. This is different from thepagesdirectory where pages are Client Components.数据获取 在
app中发生了变化。getServerSideProps、getStaticProps和getInitialProps已替换为更简单的 API。¥Data fetching has changed in
app.getServerSideProps,getStaticPropsandgetInitialPropshave been replaced with a simpler API.app目录使用嵌套文件夹来定义路由,并使用特殊的page.js文件使路由段可公开访问。¥The
appdirectory uses nested folders to define routes and a specialpage.jsfile to make a route segment publicly accessible.pages目录app目录路由 index.jspage.js/about.jsabout/page.js/aboutblog/[slug].jsblog/[slug]/page.js/blog/post-1
我们建议将页面的迁移分为两个主要步骤:
¥We recommend breaking down the migration of a page into two main steps:
步骤 1:将默认导出的页面组件移动到新的客户端组件中。
¥Step 1: Move the default exported Page Component into a new Client Component.
步骤 2:将新的客户端组件导入到
app目录内的新page.js文件中。¥Step 2: Import the new Client Component into a new
page.jsfile inside theappdirectory.
需要了解:这是最简单的迁移路径,因为它具有与
pages目录最相似的行为。¥Good to know: This is the easiest migration path because it has the most comparable behavior to the
pagesdirectory.
步骤 1:创建一个新的客户端组件
¥Step 1: Create a new Client Component
在导出客户端组件的
app目录(即app/home-page.tsx或类似目录)内创建一个新的单独文件。要定义客户端组件,请将'use client'指令添加到文件顶部(在任何导入之前)。¥Create a new separate file inside the
appdirectory (i.e.app/home-page.tsxor similar) that exports a Client Component. To define Client Components, add the'use client'directive to the top of the file (before any imports).与页面路由类似,有一个 优化步骤 在初始页面加载时将客户端组件预渲染为静态 HTML。
¥Similar to the Pages Router, there is an optimization step to prerender Client Components to static HTML on the initial page load.
将默认导出的页面组件从
pages/index.js移动到app/home-page.tsx。¥Move the default exported page component from
pages/index.jstoapp/home-page.tsx.
tsx
'use client'
// This is a Client Component (same as components in the `pages` directory)
// It receives data as props, has access to state and effects, and is
// prerendered on the server during the initial page load.
export default function HomePage({ recentPosts }) {
return (
<div>
{recentPosts.map((post) => (
<div key={post.id}>{post.title}</div>
))}
</div>
)
}步骤 2:创建新页面
¥Step 2: Create a new page
在
app目录中创建一个新的app/page.tsx文件。默认情况下这是一个服务器组件。¥Create a new
app/page.tsxfile inside theappdirectory. This is a Server Component by default.将
home-page.tsx客户端组件导入页面。¥Import the
home-page.tsxClient Component into the page.如果你在
pages/index.js中获取数据,请使用新的 数据获取 API 将数据获取逻辑直接移至服务器组件中。有关详细信息,请参阅 数据获取升级指南。¥If you were fetching data in
pages/index.js, move the data fetching logic directly into the Server Component using the new data fetching APIs. See the data fetching upgrade guide for more details.
tsx
// Import your Client Component
import HomePage from './home-page'
async function getPosts() {
const res = await fetch('https://...')
const posts = await res.json()
return posts
}
export default async function Page() {
// Fetch data directly in a Server Component
const recentPosts = await getPosts()
// Forward fetched data to your Client Component
return <HomePage recentPosts={recentPosts} />
}如果你之前的页面使用了
useRouter,你将需要更新到新的路由钩子。了解更多。¥If your previous page used
useRouter, you'll need to update to the new routing hooks. Learn more.启动你的开发服务器并访问
http://localhost:3000。你应该看到现有的索引路由,现在通过应用目录提供服务。¥Start your development server and visit
http://localhost:3000. You should see your existing index route, now served through the app directory.
步骤 5:迁移路由钩子
¥Step 5: Migrating Routing Hooks
添加了新路由以支持 app 目录中的新行为。
¥A new router has been added to support the new behavior in the app directory.
在 app 中,你应该使用从 next/navigation 导入的三个新钩子:useRouter()、usePathname() 和 useSearchParams()。
¥In app, you should use the three new hooks imported from next/navigation: useRouter(), usePathname(), and useSearchParams().
新的
useRouter钩子是从next/navigation导入的,与pages中从next/router导入的useRouter钩子具有不同的行为。¥The new
useRouterhook is imported fromnext/navigationand has different behavior to theuseRouterhook inpageswhich is imported fromnext/router.useRouter钩从next/router导入 在app目录中不受支持,但可以在pages目录中继续使用。¥The
useRouterhook imported fromnext/routeris not supported in theappdirectory but can continue to be used in thepagesdirectory.
新的
useRouter不返回pathname字符串。请改用单独的usePathname钩子。¥The new
useRouterdoes not return thepathnamestring. Use the separateusePathnamehook instead.新的
useRouter不返回query对象。搜索参数和动态路由参数现在是分开的。改用useSearchParams和useParams钩子。¥The new
useRouterdoes not return thequeryobject. Search parameters and dynamic route parameters are now separate. Use theuseSearchParamsanduseParamshooks instead.你可以使用
useSearchParams和usePathname一起监听页面变化。有关详细信息,请参阅 路由事件 部分。¥You can use
useSearchParamsandusePathnametogether to listen to page changes. See the Router Events section for more details.这些新钩子仅在客户端组件中受支持。它们不能在服务器组件中使用。
¥These new hooks are only supported in Client Components. They cannot be used in Server Components.
tsx
'use client'
import { useRouter, usePathname, useSearchParams } from 'next/navigation'
export default function ExampleClientComponent() {
const router = useRouter()
const pathname = usePathname()
const searchParams = useSearchParams()
// ...
}此外,新的 useRouter 钩子还有以下变化:
¥In addition, the new useRouter hook has the following changes:
isFallback已被删除,因为fallback具有 被替换。¥
isFallbackhas been removed becausefallbackhas been replaced.locale、locales、defaultLocales、domainLocales值已被删除,因为app目录中不再需要内置 i18n Next.js 功能。了解有关 i18n 的更多信息。¥The
locale,locales,defaultLocales,domainLocalesvalues have been removed because built-in i18n Next.js features are no longer necessary in theappdirectory. Learn more about i18n.basePath已被删除。替代方案不会成为useRouter的一部分。目前尚未实现。¥
basePathhas been removed. The alternative will not be part ofuseRouter. It has not yet been implemented.asPath已被删除,因为as的概念已从新路由中删除。¥
asPathhas been removed because the concept ofashas been removed from the new router.isReady已被删除,因为不再需要它。在 静态渲染 期间,任何使用useSearchParams()钩子的组件都将跳过预渲染步骤,而是在运行时在客户端上渲染。¥
isReadyhas been removed because it is no longer necessary. During static rendering, any component that uses theuseSearchParams()hook will skip the prerendering step and instead be rendered on the client at runtime.route已被删除。usePathname或useSelectedLayoutSegments()提供替代方案。¥
routehas been removed.usePathnameoruseSelectedLayoutSegments()provide an alternative.
¥View the useRouter() API reference.
在 pages 和 app 之间共享组件
¥Sharing components between pages and app
为了保持 pages 和 app 路由之间的组件兼容,请参阅 来自 next/compat/router 的 useRouter 钩子。这是来自 pages 目录的 useRouter 钩子,但旨在用于在路由之间共享组件时。一旦你准备好仅在 app 路由上使用它,请更新到新的 useRouter 从 next/navigation。
¥To keep components compatible between the pages and app routers, refer to the useRouter hook from next/compat/router. This is the useRouter hook from the pages directory, but intended to be used while sharing components between routers. Once you are ready to use it only on the app router, update to the new useRouter from next/navigation.
步骤 6:迁移数据获取方法
¥Step 6: Migrating Data Fetching Methods
pages 目录使用 getServerSideProps 和 getStaticProps 来获取页面数据。在 app 目录中,这些以前的数据获取函数被基于 fetch() 和 async React Server 组件构建的 更简单的 API 所取代。
¥The pages directory uses getServerSideProps and getStaticProps to fetch data for pages. Inside the app directory, these previous data fetching functions are replaced with a simpler API built on top of fetch() and async React Server Components.
tsx
export default async function Page() {
// This request should be cached until manually invalidated.
// Similar to `getStaticProps`.
// `force-cache` is the default and can be omitted.
const staticData = await fetch(`https://...`, { cache: 'force-cache' })
// This request should be refetched on every request.
// Similar to `getServerSideProps`.
const dynamicData = await fetch(`https://...`, { cache: 'no-store' })
// This request should be cached with a lifetime of 10 seconds.
// Similar to `getStaticProps` with the `revalidate` option.
const revalidatedData = await fetch(`https://...`, {
next: { revalidate: 10 },
})
return <div>...</div>
}服务器端渲染(getServerSideProps)
¥Server-side Rendering (getServerSideProps)
在 pages 目录中,getServerSideProps 用于在服务器上获取数据并将 props 转发到文件中默认导出的 React 组件。页面的初始 HTML 是从服务器预渲染的,然后是浏览器中的 "hydrating" 页面(使其具有交互性)。
¥In the pages directory, getServerSideProps is used to fetch data on the server and forward props to the default exported React component in the file. The initial HTML for the page is prerendered from the server, followed by "hydrating" the page in the browser (making it interactive).
在 App Router 中,我们可以使用 服务器组件 将数据获取放在 React 组件内。这使我们能够向客户端发送更少的 JavaScript,同时保留服务器渲染的 HTML。
¥In the App Router, we can colocate our data fetching inside our React components using Server Components. This allows us to send less JavaScript to the client, while maintaining the rendered HTML from the server.
通过将 cache 选项设置为 no-store,我们可以指示获取的数据应该是 永远不会被缓存。这与 pages 目录中的 getServerSideProps 类似。
¥By setting the cache option to no-store, we can indicate that the fetched data should never be cached. This is similar to getServerSideProps in the pages directory.
tsx
// `app` directory
// This function can be named anything
async function getProjects() {
const res = await fetch(`https://...`, { cache: 'no-store' })
const projects = await res.json()
return projects
}
export default async function Dashboard() {
const projects = await getProjects()
return (
<ul>
{projects.map((project) => (
<li key={project.id}>{project.name}</li>
))}
</ul>
)
}访问请求对象
¥Accessing Request Object
在 pages 目录中,你可以基于 Node.js HTTP API 检索基于请求的数据。
¥In the pages directory, you can retrieve request-based data based on the Node.js HTTP API.
例如,你可以从 getServerSideProps 检索 req 对象,并使用它来检索请求的 cookie 和标头。
¥For example, you can retrieve the req object from getServerSideProps and use it to retrieve the request's cookies and headers.
app 目录公开了新的只读函数来检索请求数据:
¥The app directory exposes new read-only functions to retrieve request data:
headers:基于 Web Headers API,可以在 服务器组件 内部使用来检索请求标头。¥
headers: Based on the Web Headers API, and can be used inside Server Components to retrieve request headers.cookies:基于 Web Cookies API,可以在 服务器组件 内部使用来检索 cookie。¥
cookies: Based on the Web Cookies API, and can be used inside Server Components to retrieve cookies.
tsx
// `app` directory
import { cookies, headers } from 'next/headers'
async function getData() {
const authHeader = (await headers()).get('authorization')
return '...'
}
export default async function Page() {
// You can use `cookies` or `headers` inside Server Components
// directly or in your data fetching function
const theme = (await cookies()).get('theme')
const data = await getData()
return '...'
}静态站点生成 (getStaticProps)
¥Static Site Generation (getStaticProps)
在 pages 目录中,getStaticProps 函数用于在构建时预渲染页面。此函数可用于从外部 API 或直接从数据库获取数据,并将这些数据在构建期间生成时传递到整个页面。
¥In the pages directory, the getStaticProps function is used to pre-render a page at build time. This function can be used to fetch data from an external API or directly from a database, and pass this data down to the entire page as it's being generated during the build.
在 app 目录下,用 fetch() 取数据会默认到 cache: 'force-cache',cache: 'force-cache' 会缓存请求数据,直到手动失效。这与 pages 目录中的 getStaticProps 类似。
¥In the app directory, data fetching with fetch() will default to cache: 'force-cache', which will cache the request data until manually invalidated. This is similar to getStaticProps in the pages directory.
动态路径 (getStaticPaths)
¥Dynamic paths (getStaticPaths)
在 pages 目录中,getStaticPaths 函数用于定义应在构建时预渲染的动态路径。
¥In the pages directory, the getStaticPaths function is used to define the dynamic paths that should be pre-rendered at build time.
在 app 目录中,getStaticPaths 被替换为 generateStaticParams。
¥In the app directory, getStaticPaths is replaced with generateStaticParams.
generateStaticParams 的行为与 getStaticPaths 类似,但具有用于返回路由参数的简化 API,并且可以在 layouts 内部使用。generateStaticParams 的返回形状是一个段数组,而不是嵌套的 param 对象数组或解析路径字符串。
¥generateStaticParams behaves similarly to getStaticPaths, but has a simplified API for returning route parameters and can be used inside layouts. The return shape of generateStaticParams is an array of segments instead of an array of nested param objects or a string of resolved paths.
对于 app 目录中的新模型,使用名称 generateStaticParams 比 getStaticPaths 更合适。get 前缀被替换为更具描述性的 generate,现在不再需要 getStaticProps 和 getServerSideProps,单独使用它会更好。Paths 后缀被替换为 Params,这更适合具有多个动态段的嵌套路由。
¥Using the name generateStaticParams is more appropriate than getStaticPaths for the new model in the app directory. The get prefix is replaced with a more descriptive generate, which sits better alone now that getStaticProps and getServerSideProps are no longer necessary. The Paths suffix is replaced by Params, which is more appropriate for nested routing with multiple dynamic segments.
更换 fallback
¥Replacing fallback
在 pages 目录中,从 getStaticPaths 返回的 fallback 属性用于定义在构建时未预渲染的页面的行为。此属性可以设置为 true 以在生成页面时显示后备页面,设置为 false 以显示 404 页面,或设置为 blocking 以在请求时生成页面。
¥In the pages directory, the fallback property returned from getStaticPaths is used to define the behavior of a page that isn't pre-rendered at build time. This property can be set to true to show a fallback page while the page is being generated, false to show a 404 page, or blocking to generate the page at request time.
在 app 目录中,config.dynamicParams property 控制 generateStaticParams 之外的参数的处理方式:
¥In the app directory the config.dynamicParams property controls how params outside of generateStaticParams are handled:
true:(默认)generateStaticParams中未包含的动态段是按需生成的。¥
true: (default) Dynamic segments not included ingenerateStaticParamsare generated on demand.false:未包含在generateStaticParams中的动态段将返回 404。¥
false: Dynamic segments not included ingenerateStaticParamswill return a 404.
这替换了 pages 目录中 getStaticPaths 的 fallback: true | false | 'blocking' 选项。fallback: 'blocking' 选项不包含在 dynamicParams 中,因为 'blocking' 和 true 之间的差异对于流式传输来说可以忽略不计。
¥This replaces the fallback: true | false | 'blocking' option of getStaticPaths in the pages directory. The fallback: 'blocking' option is not included in dynamicParams because the difference between 'blocking' and true is negligible with streaming.
当 dynamicParams 设置为 true(默认值)时,当请求尚未生成的路由段时,它将被服务器渲染并缓存。
¥With dynamicParams set to true (the default), when a route segment is requested that hasn't been generated, it will be server-rendered and cached.
增量静态再生(getStaticProps 和 revalidate)
¥Incremental Static Regeneration (getStaticProps with revalidate)
在 pages 目录中,getStaticProps 功能允许你添加 revalidate 字段,以在一定时间后自动重新生成页面。
¥In the pages directory, the getStaticProps function allows you to add a revalidate field to automatically regenerate a page after a certain amount of time.
在 app 目录中,使用 fetch() 获取数据可以使用 revalidate,revalidate 会将请求缓存指定的秒数。
¥In the app directory, data fetching with fetch() can use revalidate, which will cache the request for the specified amount of seconds.
API 路由
¥API Routes
API 路由继续在 pages/api 目录中工作,没有任何更改。但是,它们已被 app 目录中的 路由处理程序 替换。
¥API Routes continue to work in the pages/api directory without any changes. However, they have been replaced by Route Handlers in the app directory.
路由处理程序允许你使用 Web 请求 和 响应 API 为给定路由创建自定义请求处理程序。
¥Route Handlers allow you to create custom request handlers for a given route using the Web Request and Response APIs.
ts
export async function GET(request: Request) {}需要了解:如果你之前使用 API 路由从客户端调用外部 API,现在可以使用 服务器组件 来安全地获取数据。了解有关 数据获取 的更多信息。
¥Good to know: If you previously used API routes to call an external API from the client, you can now use Server Components instead to securely fetch data. Learn more about data fetching.
单页应用
¥Single-Page Applications
如果你同时还从单页应用 (SPA) 迁移到 Next.js,请参阅我们的 documentation 了解更多信息。
¥If you are also migrating to Next.js from a Single-Page Application (SPA) at the same time, see our documentation to learn more.
步骤 7:样式
¥Step 7: Styling
在 pages 目录中,全局样式表仅限于 pages/_app.js。有了 app 目录,这个限制就被解除了。全局样式可以添加到任何布局、页面或组件中。
¥In the pages directory, global stylesheets are restricted to only pages/_app.js. With the app directory, this restriction has been lifted. Global styles can be added to any layout, page, or component.
Tailwind CSS
如果你使用的是 Tailwind CSS,则需要将 app 目录添加到 tailwind.config.js 文件中:
¥If you're using Tailwind CSS, you'll need to add the app directory to your tailwind.config.js file:
你还需要在 app/layout.js 文件中导入全局样式:
¥You'll also need to import your global styles in your app/layout.js file:
了解有关 使用 Tailwind CSS 进行样式设置 的更多信息
¥Learn more about styling with Tailwind CSS
将应用路由与页面路由一起使用
¥Using App Router together with Pages Router
在由不同的 Next.js 路由提供的路由之间导航时,将会出现硬导航。使用 next/link 的自动链接预取不会跨路由预取。
¥When navigating between routes served by the different Next.js routers, there will be a hard navigation. Automatic link prefetching with next/link will not prefetch across routers.
相反,你可以在 App Router 和 Pages Router 之间 优化导航,以保留预取和快速页面转换。了解更多。
¥Instead, you can optimize navigations between App Router and Pages Router to retain the prefetched and fast page transitions. Learn more.
代码模组
¥Codemods
Next.js 提供 Codemod 转换,以帮助在功能被弃用时升级代码库。请参阅 代码模组 了解更多信息。
¥Next.js provides Codemod transformations to help upgrade your codebase when a feature is deprecated. See Codemods for more information.