Serverless 排程:Vercel Cron Jobs 實戰

在這個 AI 與現代 Web 開發的時代,我們幾乎都是使用 Next.js 等框架撰寫全端網站,並將其部署到 Vercel 平台上。

過去,如果你把 Next.js 部署到 Vercel,想要做「每晚 12 點統計資料庫數據」的任務,你必須像我們第二章教的那樣,自己去註冊 cron-job.org 來戳 API。但 Vercel 官方聽到了開發者的心聲,現在他們原生推出了 Vercel Cron Jobs 功能!

使用 Vercel Cron Jobs 的好處是:與專案深度整合、免註冊外部服務、自帶強大的資安防護

實作 Vercel Cron Jobs 的三大步驟

在 Next.js (App Router) 中實作 Vercel Cron 非常簡單。我們只需要準備一個普通的 API 端點,並在設定檔中告訴 Vercel 何時去呼叫它即可。

步驟 1:建立 API Route

首先,在你的 Next.js 專案中建立一個專門給 Cronjob 呼叫的 API 端點。 例如建立檔案 src/app/api/cron/daily-report/route.ts

import { NextResponse } from 'next/server';

export async function GET(request: Request) {
  // 檢查安全性 (後面步驟會解釋)
  const authHeader = request.headers.get('authorization');
  
  // 為了安全起見,這裡先印出被呼叫的時間
  console.log(`[Cron Job Triggered] Time: ${new Date().toISOString()}`);

  try {
    // ============================================
    // 在這裡寫你的業務邏輯!
    // 例如:從 Supabase 撈取昨日訂單,寄送 Email 報表
    // await generateAndSendDailyReport();
    // ============================================

    return NextResponse.json(
      { success: true, message: 'Daily report processed successfully' },
      { status: 200 }
    );
  } catch (error) {
    console.error('Cron job error:', error);
    return NextResponse.json(
      { success: false, message: 'Failed to process job' },
      { status: 500 }
    );
  }
}

步驟 2:加入 Vercel.json 設定檔

接下來,在你的專案根目錄(與 package.json 同層)建立一個名為 vercel.json 的檔案。

這個檔案是 Vercel 的專屬設定檔,我們在裡面宣告我們的 cron 排程:

{
  "crons": [
    {
      "path": "/api/cron/daily-report",
      "schedule": "0 8 * * *"
    }
  ]
}

這裡的設定非常直觀:

  • path:告訴 Vercel 時間到了要去呼叫哪個相對路徑的 API。
  • schedule:一樣是使用 Crontab 語法。這裡設定每天早上 8 點 (這裡的時區同樣預設為 UTC,請記得自行換算!台灣早上 8 點 = UTC 0 0 * * *)。

[!TIP] Vercel Hobby (免費版) 的限制 如果你是免費版帳號,Vercel 規定一天最多只能執行一次 Cron job (也就是每天的限制額度為 1 次)。 如果你的腳本需要每小時執行,你必須升級至 Vercel Pro (每月 $20),或者退而求其次,乖乖回去使用我們教過的 cron-job.org

步驟 3:安全性防護 (CRON_SECRET)

這是 Vercel Cron Jobs 最貼心的一點!

如果你的 API URL (如 /api/cron/daily-report) 暴露在網路上,任何人都可以自己發送請求來觸發你的報表生成,這非常危險。

為了解決這個問題,當 Vercel 讀取到你的 vercel.json 並為你建立 Cronjob 時,它會自動在你的專案環境變數中,注入一個超級複雜的密碼:CRON_SECRET

每次 Vercel 自動觸發你的 API 時,它的 HTTP Header 都會帶著這個金鑰: Authorization: Bearer <你的_CRON_SECRET>

所以,我們必須修改我們步驟 1 的 API,加入這層無堅不摧的防護:

import { NextResponse } from 'next/server';

export async function GET(request: Request) {
  // 1. 取得請求中的 Authorization Header
  const authHeader = request.headers.get('authorization');
  
  // 2. 確保 Vercel 環境中有設定 CRON_SECRET
  const cronSecret = process.env.CRON_SECRET;
  
  // 3. 嚴格比對!如果金鑰不對,直接拒絕存取
  if (!cronSecret || authHeader !== `Bearer ${cronSecret}`) {
    return NextResponse.json(
      { success: false, message: 'Unauthorized Request' },
      { status: 401 }
    );
  }

  // 4. 金鑰正確,放行執行核心邏輯
  console.log("授權成功,開始執行排程任務...");
  
  return NextResponse.json({ success: true });
}

測試與上線

當你把程式碼推送到 GitHub,Vercel 自動部署完成後,你可以進入 Vercel 的專案儀表板。

點擊上方選單的 "Settings" -> 左邊的 "Cron Jobs"。 在這裡,你會看到你剛剛在 vercel.json 裡面設定好的任務清單。Vercel 還貼心地提供了一個 "Run" 的手動測試按鈕,點擊它就能馬上觸發你的 API,方便你測試 CRON_SECRET 有沒有正確生效!

透過 Vercel Cron Jobs,只要簡簡單單一個設定檔,你就能打造出擁有銀行等級安全防護的全端自動化服務!

解鎖完整教學內容

本章為付費內容。加入專案即可解鎖超過 5000 字的深度解析,包含 10 個以上神級 Prompt 與真實 Source Code 範例!