⏱️

Vercel の Cron Jobs を nuxt.config.ts で設定する

に公開

こんにちは、合同会社Steg 代表の keigo (@Kspace_trk) と申します。
本記事では、Nuxt / Nitro プロジェクトにおける Vercel の Cron Jobs の設定方法をご紹介します。

執筆時点での動作確認環境

Package Version
Nuxt ^3.16.2
Nitro ^2.11.8

Vercel Cron Jobsとは

Vercel Cron Jobs は、Vercel 上にデプロイしたアプリの Route Handler (Serverless Function) を、指定した日時や間隔で自動実行してくれるスケジューラーです。

https://vercel.com/docs/cron-jobs

GitHub Actions や外部サーバーの cron を利用しなくても、Vercel だけで「毎日5時にDBのバックアップを取る」といった定期タスクを完結できます。

通常、Vercel Cron Jobs を利用するには、プロジェクトルートに vercel.json を配置し、以下の設定を記述します。

vercel.json
{
  "crons": [
    {
      "path": "/api/cron/example-task",
      "schedule": "0 5 * * *"   // 毎日 05:00 (UTC) = 日本時間 14:00
    }
  ]
}

Nuxt / Nitro プロジェクトでは、設定ファイル(nuxt.config.ts もしくは nitro.config.ts)にこの設定が統合されています。

実装手順

本記事で紹介する実装方法は、Nitro Tasks API として正式に実装される前の、暫定的な手法です。

https://github.com/nitrojs/nitro/issues/1974#issuecomment-2573129113

最新情報については、Nitro Tasks API の Tracker issue をご覧ください。

1. nuxt.config.ts に Cron Job を追加する

nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    experimental: {
      tasks: true,  // experimentalな機能を有効化する
    },
    vercel: {
      crons: [
        {
          path: '/api/cron/ping',   // 実行対象のエンドポイント
          schedule: '0 5 * * *'   // 毎日 05:00 (UTC) = 日本時間 14:00
        }
      ]
    }
  }
})

2. APIエンドポイントを作成

Cron Jobsは、特定の関数ではなく定義しているイベントハンドラーが実行されます。

config ファイルで指定した path に対応するイベントハンドラーのファイルを作成しましょう。

server/api/cron/ping.ts
export default defineEventHandler(async () => {
  // ここに定期実行したい処理を書く
  console.log('pong!', new Date().toISOString())
  return { ok: true }
})

Vercel Cron Jobsから実行されるのはGETリクエストのみです。リクエストボディを渡すことは出来ないため注意しましょう。

3. CRON_SECRET で外部アクセスをブロック

Vercel Cron Jobs から送信されるリクエストには、自動的に Authorization ヘッダー が付与されます。
Authorization ヘッダー には、事前にVercelで設定した CRON_TOKEN 環境変数の値が Bearer <CRON_TOKEN> の形でセットされます。
リクエストの値と環境変数の値が一致することをイベントハンドラー内で検証しましょう。

server/api/cron/ping.ts
export default defineEventHandler((event) => {
  const config = useRuntimeConfig()
  const token = getRequestHeader(event, 'authorization')?.replace('Bearer ', '')
  if (token !== config.CRON_SECRET) {
    throw createError({ statusCode: 401, statusMessage: 'Unauthorized' })
  }

  // ここに定期実行したい処理を書く
  console.log('pong!', new Date().toISOString())
  return { ok: true }
})

Hobby プランの制限について

Vercel Cron Jobsでは、プランごとに以下の制限が設けられています。

プラン 作成可能ジョブ数 呼び出し頻度 精度
Hobby 2 件まで 1 日 1 回 時単位(±59 分の揺らぎ)
Pro 40 件 無制限 分単位
Ent 100 件 無制限 分単位
  • Hobby では 3 件以上定義するとデプロイ時にエラーになります。
  • */15 * * * * のような分精度の式を書いても ±59 分の遅延が入るので注意しましょう。

まとめ

Nuxt / Nitro プロジェクトに Vercel Cron Jobs の設定が統合されたことにより、より簡単に定期実行処理を実装できるようになりました。
Vercelでホスティングしているアプリケーションで定期実行処理を設定したい際は、是非試してみてください!

Steg Inc.

Discussion