after
after
を使用すると、レスポンス(またはプリレンダリング)が完了した後に実行される処理をスケジュールすることができます。これはロギングや分析など、レスポンスをブロックすべきではないタスクやその他の副作用に便利です。
この関数はサーバーコンポーネント(generateMetadata
を含む)、サーバーアクション、ルートハンドラー、およびミドルウェアで使用できます。
この関数はレスポンス(またはプリレンダリング)の完了後に実行されるコールバックを受け取ります:
import { after } from 'next/server'
// カスタムロギング関数
import { log } from '@/app/utils'
export default function Layout({ children }: { children: React.ReactNode }) {
after(() => {
// レイアウトがレンダリングされ、ユーザーに送信された後に実行
log()
})
return <>{children}</>
}
補足:
after
は動的APIではなく、これを呼び出してもルートが動的になることはありません。静的ページ内で使用される場合、コールバックはビルド時、またはページが再検証されるときに実行されます。
リファレンス
パラメータ
- レスポンス(またはプリレンダリング)の完了後に実行されるコールバック関数。
実行時間
after
はプラットフォームのデフォルトまたは設定されたルートの最大実行時間まで実行されます。プラットフォームがサポートしている場合は、maxDuration
ルートセグメント設定を使用してタイムアウト制限を設定できます。
補足
after
はレスポンスが正常に完了しなかった場合でも実行されます。これにはエラーがスローされた場合や、notFound
またはredirect
が呼び出された場合も含まれます。- React
cache
を使用してafter
内で呼び出される関数を重複排除できます。 after
は他のafter
呼び出し内にネストできます。例えば、追加機能を追加するためにafter
呼び出しをラップするユーティリティ関数を作成できます。
例
リクエストAPIとの併用
サーバーアクションやルートハンドラーでafter
内でcookies
やheaders
などのリクエスト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' },
})
}
ただし、サーバーコンポーネント内のafter
でこれらのリクエストAPIを使用することはできません。これは、Next.jsが部分的プリレンダリングをサポートするためにリクエストAPIにアクセスするツリーのどの部分かを把握する必要があるためですが、after
はReactのレンダリングライフサイクルの後に実行されます。
プラットフォームサポート
デプロイオプション | サポート状況 |
---|---|
Node.jsサーバー | あり |
Dockerコンテナ | あり |
静的エクスポート | なし |
アダプター | プラットフォーム依存 |
Next.jsをセルフホスティングする際のafter
の設定方法について学びましょう。
リファレンス: サーバーレスプラットフォームでの
サーバーレスコンテキストでafter
のサポートafter
を使用するには、レスポンスが送信された後に非同期タスクが完了するのを待機する必要があります。Next.jsとVercelでは、これはwaitUntil(promise)
というプリミティブを使用して、waitUntil
に渡されたすべてのプロミスが解決されるまでサーバーレス呼び出しの寿命を延長することで実現されます。
ユーザーが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 が導入されました。 |