after 允许你安排工作在响应(或预渲染)完成之后执行。这对于不应阻塞响应的任务和其他副作用非常有用,例如日志记录和分析。
它可以在 服务器组件(包括 generateMetadata)、服务器 Actions、路由处理器 和 代理 中使用。
该函数接受一个回调函数,该回调函数将在响应(或预渲染)完成之后执行:
import { after } from 'next/server'
// Custom logging function
import { log } from '@/app/utils'
export default function Layout({ children }: { children: React.ReactNode }) {
after(() => {
// Execute after the layout is rendered and sent to the user
log()
})
return <>{children}</>
}import { after } from 'next/server'
// Custom logging function
import { log } from '@/app/utils'
export default function Layout({ children }) {
after(() => {
// Execute after the layout is rendered and sent to the user
log()
})
return <>{children}</>
}须知:
after不是一个 动态 API,调用它不会导致路由变为动态。如果它在静态页面中使用,回调将在构建时或页面重新验证时执行。
after 将在平台默认或配置的路由最大持续时间内运行。如果你的平台支持,你可以使用 maxDuration 路由段配置来配置超时限制。
after 也会执行。这包括抛出错误或调用 notFound 或 redirect 的情况。cache 来对 after 内部调用的函数进行去重。after 可以嵌套在其他 after 调用中,例如,你可以创建封装 after 调用的工具函数以添加额外功能。你可以在 Server Actions 和 Route Handlers 中,在 after 内部使用请求 API,例如 cookies 和 headers。这对于在修改后记录活动非常有用。例如:
import { after } from 'next/server'
import { cookies, headers } from 'next/headers'
import { logUserAction } from '@/app/utils'
export async function POST(request: Request) {
// Perform mutation
// ...
// Log user activity for analytics
after(async () => {
const userAgent = (await headers().get('user-agent')) || 'unknown'
const sessionCookie =
(await cookies().get('session-id'))?.value || 'anonymous'
logUserAction({ sessionCookie, userAgent })
})
return new Response(JSON.stringify({ status: 'success' }), {
status: 200,
headers: { 'Content-Type': 'application/json' },
})
}import { after } from 'next/server'
import { cookies, headers } from 'next/headers'
import { logUserAction } from '@/app/utils'
export async function POST(request) {
// Perform mutation
// ...
// Log user activity for analytics
after(async () => {
const userAgent = (await headers().get('user-agent')) || 'unknown'
const sessionCookie =
(await cookies().get('session-id'))?.value || 'anonymous'
logUserAction({ sessionCookie, userAgent })
})
return new Response(JSON.stringify({ status: 'success' }), {
status: 200,
headers: { 'Content-Type': 'application/json' },
})
}然而,你不能在 服务器组件 的 after 内部使用这些请求 API。这是因为 Next.js 需要知道树的哪个部分访问了请求 API 以支持 缓存组件,而 after 是在 React 的渲染生命周期之后运行的。
| 部署选项 | 支持 |
|---|---|
| Node.js 服务器 | 是 |
| Docker 容器 | 是 |
| 静态导出 | 否 |
| 适配器 | 平台相关 |
了解如何在自托管 Next.js 时 配置 after。
after在无服务器上下文中使用 after 需要在响应发送后等待异步任务完成。在 Next.js 和 Vercel 中,这是通过一个名为 waitUntil(promise) 的原语实现的,它会延长无服务器调用的生命周期,直到所有传递给 waitUntil 的 Promise 都已解决。
如果你希望你的用户能够运行 after,你将不得不提供一个行为类似 waitUntil 的实现。
当调用 after 时,Next.js 将按如下方式访问 waitUntil:
const RequestContext = globalThis[Symbol.for('@next/request-context')]
const contextValue = RequestContext?.get()
const waitUntil = contextValue?.waitUntil这意味着 globalThis[Symbol.for('@next/request-context')] 应该包含一个如下所示的对象:
type NextRequestContext = {
get(): NextRequestContextValue | undefined
}
type NextRequestContextValue = {
waitUntil?: (promise: Promise<any>) => void
}以下是一个实现示例。
import { AsyncLocalStorage } from 'node:async_hooks'
const RequestContextStorage = new AsyncLocalStorage<NextRequestContextValue>()
// Define and inject the accessor that next.js will use
const RequestContext: NextRequestContext = {
get() {
return RequestContextStorage.getStore()
},
}
globalThis[Symbol.for('@next/request-context')] = RequestContext
const handler = (req, res) => {
const contextValue = { waitUntil: YOUR_WAITUNTIL }
// Provide the value
return RequestContextStorage.run(contextValue, () => nextJsHandler(req, res))
}| 版本历史 | 描述 |
|---|---|
v15.1.0 | after 变为稳定版。 |
v15.0.0-rc | 引入了 unstable_after。 |