after
after を使用すると、レスポンス(またはプリレンダー)が終了した後に実行される処理をスケジュール設定できます。これはレスポンスをブロックしてはいけないログやアナリティクスなどのタスクや副作用に便利です。
Server Components(generateMetadata を含む)、Server Actions、Route Handlers、Proxy で使用できます。
この関数は、レスポンス(またはプリレンダー)が終了した後に実行されるコールバックを受け入れます:
import { after } from 'next/server'
// カスタムログ関数
import { log } from '@/app/utils'
export default function Layout({ children }: { children: React.ReactNode }) {
after(() => {
// レイアウトのレンダリング後、ユーザーへ送信された後に実行
log()
})
return <>{children}</>
}補足:
afterは Dynamic API ではなく、呼び出してもルートが動的にはなりません。静的ページで使用される場合、コールバックはビルド時、またはページが再検証されるたびに実行されます。
Reference
パラメータ
- レスポンス(またはプリレンダー)が終了した後に実行されるコールバック関数。
Duration
after はプラットフォームのデフォルトまたはルートの設定済み最大継続時間で実行されます。プラットフォームがサポートしている場合、maxDuration ルートセグメント設定を使用してタイムアウト制限を設定できます。
補足
afterはレスポンスが正常に完了しなかった場合でも実行されます。エラーがスローされた場合、またはnotFoundやredirectが呼び出された場合を含みます。- React の
cacheを使用して、after内で呼び出された関数を重複排除できます。 afterは他のafter呼び出しの内側にネストできます。例えば、after呼び出しをラップして追加機能を追加するユーティリティ関数を作成できます。
例
Request API と共に使用
Server Actions と Route Handlers の after 内で、cookies や headers などの request API を使用できます。これはミューテーション後のアクティビティをログに記録するのに便利です。例えば:
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' },
})
}ただし、Server Components の after 内ではこれらの request API を使用できません。これは Next.js が Cache Components をサポートするためにツリーのどの部分が request API にアクセスするかを知る必要があるためですが、after は React のレンダリングライフサイクルの後に実行されます。
プラットフォームサポート
| デプロイオプション | サポート |
|---|---|
| Node.js server | Yes |
| Docker container | Yes |
| Static export | No |
| Adapters | Platform-specific |
Next.js を自己ホストする場合の after の設定 方法について詳しくお読みください。
Reference: サーバーレスプラットフォームの 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))
}Version History
| Version History | Description |
|---|---|
v15.1.0 | after は安定版になりました。 |
v15.0.0-rc | unstable_after が導入されました。 |