after
after
允许您在响应(或預渲染)完成後安排執行工作。這對於不應阻塞回應的任務和其他副作用(例如日誌記錄和分析)非常有用。
它可以用於伺服器元件 (Server Components)(包括 generateMetadata
)、伺服器動作 (Server Actions)、路由處理器 (Route Handlers) 和 中介軟體 (Middleware)。
此函數接受一個回調函數,該回調將在響應(或預渲染)完成後執行:
import { after } from 'next/server'
// 自訂日誌函數
import { log } from '@/app/utils'
export default function Layout({ children }: { children: React.ReactNode }) {
after(() => {
// 在佈局渲染並發送給用戶後執行
log()
})
return <>{children}</>
}
import { after } from 'next/server'
// 自訂日誌函數
import { log } from '@/app/utils'
export default function Layout({ children }) {
after(() => {
// 在佈局渲染並發送給用戶後執行
log()
})
return <>{children}</>
}
須知事項:
after
不是動態 API (Dynamic API),呼叫它不會導致路由變為動態。如果在靜態頁面中使用,回調將在建置時或在頁面重新驗證時執行。
參考
參數
- 一個回調函數,將在響應(或預渲染)完成後執行。
持續時間
after
將運行至您路由的預設或配置的最大持續時間。如果您的平台支援,可以使用 maxDuration
路由段配置來設定超時限制。
須知事項
- 即使響應未成功完成,
after
也會執行。包括當拋出錯誤或呼叫notFound
或redirect
時。 - 您可以使用 React 的
cache
來消除after
內呼叫的函數重複。 after
可以嵌套在其他after
呼叫中,例如,您可以建立封裝after
呼叫的實用函數以添加額外功能。
範例
與請求 API 一起使用
您可以在伺服器動作 (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) {
// 執行變異
// ...
// 記錄用戶活動以進行分析
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) {
// 執行變異
// ...
// 記錄用戶活動以進行分析
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' },
})
}
然而,您不能在伺服器元件 (Server Components) 中的 after
內使用這些請求 API。這是因為 Next.js 需要知道樹的哪部分訪問了請求 API 以支援部分預渲染 (Partial Prerendering),但 after
在 React 的渲染生命週期之後運行。
平台支援
部署選項 | 支援情況 |
---|---|
Node.js 伺服器 | 是 |
Docker 容器 | 是 |
靜態匯出 (Static export) | 否 |
適配器 (Adapters) | 依平台而定 |
了解如何配置 after
當自行託管 Next.js 時。
參考:支援無伺服器平台的
在無伺服器環境中使用 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>()
// 定義並注入 Next.js 將使用的存取器
const RequestContext: NextRequestContext = {
get() {
return RequestContextStorage.getStore()
},
}
globalThis[Symbol.for('@next/request-context')] = RequestContext
const handler = (req, res) => {
const contextValue = { waitUntil: YOUR_WAITUNTIL }
// 提供值
return RequestContextStorage.run(contextValue, () => nextJsHandler(req, res))
}
版本歷史
版本歷史 | 描述 |
---|---|
v15.1.0 | after 成為穩定版。 |
v15.0.0-rc | 引入 unstable_after 。 |