Menu

after

afterを使用すると、レスポンス(またはプリレンダリング)が完了した後に実行される処理をスケジュールすることができます。これはロギングや分析など、レスポンスをブロックすべきではないタスクやその他の副作用に便利です。

この関数はサーバーコンポーネントgenerateMetadataを含む)、サーバーアクションルートハンドラー、およびミドルウェアで使用できます。

この関数はレスポンス(またはプリレンダリング)の完了後に実行されるコールバックを受け取ります:

app/layout.tsx
TypeScript
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内でcookiesheadersなどのリクエストAPIを使用することができます。これはミューテーション後のアクティビティを記録するのに便利です。例えば:

app/api/route.ts
TypeScript
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.0afterが安定版になりました。
v15.0.0-rcunstable_afterが導入されました。