Vercelで簡単に実装！Cron Jobsの設定方法と活用例

## #1 イントロダクション
### #1-1 記事の目的と対象読者
この記事では、「Vercelを利用したCron Jobの利用例」を紹介し、VercelプラットフォームでのCron Jobの設定方法や実際のプロジェクトでの利用方法を解説します。記事の目的は、Vercelを利用してCron Jobを実装する方法を学び、定期的なタスクの自動化に役立てることです。

対象読者としては、初めてVercelを使う方や、VercelでのCron Jobの設定方法に慣れていない方を想定しています。記事を読むことで、VercelでのCron Jobの基本的な設定方法や実際のプロジェクトでの応用例を理解し、自分のプロジェクトでもCron Jobを活用できるようになることを目指します。
### #1-2 VercelとCron Jobの簡単な説明
Vercelとは、開発者向けのクラウドプラットフォームであり、主にサーバーレスアプリケーションや静的サイトの開発、デプロイ、ホスティングを簡単に行えるように設計されています。Vercelは、Next.jsやReactをはじめとする様々なフレームワークに対応しており、スムーズな開発体験を提供しています。

Cron Jobは、UNIX系オペレーティングシステムで利用されるスケジューリング機能で、定期的に繰り返し実行するタスク（Cronタスク）を自動化するための仕組みです。Cron Jobは、バックアップの取得やデータの更新など、一定の間隔で行うべき作業を効率的に管理することができます。

Vercelでは、Cron Jobの仕組みを利用して、サーバーレス関数（Serverless Functions）を定期的に実行することができます。これにより、Vercelプラットフォーム上でCron Jobを簡単に設定し、継続的なタスク管理や自動化を実現することが可能です。


## #2 VercelでのCron Jobの設定方法
### #2-1 Serverless Functionsの紹介
関数をAPIエンドポイントとして公開し、HTTPリクエストを受け付けることで実行されます。
例えば、[アプリケーションのURL]/api/cronをたたくと、/pages/api/cron.tsが実行されます。

### #2-2 VercelのCron Jobの仕組み
Vercelでは、Cron Jobを利用して、Serverless Functionsを定期的に実行することができます。これにより、Vercelプラットフォーム上でCron Jobを簡単に設定し、定期的なタスクの自動化や継続的なタスク管理を実現することが可能です。

VercelのCron Jobは、特定のスケジュールに従ってServerless Functionsをトリガーするための機能です。これにより、定期的に実行する必要があるバックエンド処理やデータの更新、メンテナンスタスクなどを自動化できます。

Cron Jobは、Vercelのvercel.json設定ファイル内で簡単に設定できます。この設定ファイルにCron式を記述することで、関数の実行スケジュールを指定できます。Cron式は、分・時・日・月・曜日の5つのフィールドで構成され、それぞれのフィールドに数値やワイルドカードを指定することで実行タイミングを決定します。

VercelのCron Jobの仕組みを利用することで、以下のような利点があります。

- Vercelプラットフォーム上でのCron Jobの簡単な設定
- Serverless Functionsとのシームレスな統合
- 定期的なバックエンド処理やデータ更新の自動化

このような仕組みにより、VercelではCron Jobを簡単かつ効果的に活用することができます。

### #2-3 Cron Jobの設定方法

VercelでCron Jobを設定する方法は簡単で、以下の手順に従って行います。

1. Serverless Functionsの作成:
まず、Vercelで実行するServerless Functionsを作成します。関数を作成したら、APIエンドポイントとして公開され、HTTPリクエストで実行されます。

2. `vercel.json`設定ファイルの作成:
プロジェクトのルートディレクトリに`vercel.json`という名前の設定ファイルを作成します。このファイルでは、Vercelプラットフォームに関する様々な設定を行うことができます。

3. Cron Jobの設定:
Cron Jobに関連する設定を行います。以下は、サンプルの設定です。

    ```json
    {
    "crons": [
      {
        "path": "/api/cron",
        "schedule": "0 * * * *"
      }
    ]
    }
    ```

この例では、`/pages/api/cron`というパスにある関数が、毎時0分に実行されるように設定しています。`cron`プロパティには、Cron式を指定します。Cron式は、分・時・日・月・曜日の5つのフィールドで構成されており、それぞれのフィールドに数値やワイルドカードを指定することで実行タイミングを決定します。

４. デプロイ:
プロジェクトをVercelにデプロイします。デプロイが完了すると、指定されたスケジュールでCron Jobが実行され、関数が定期的に呼び出されます。

これらの手順に従って、VercelプラットフォームでCron Jobを設定することができます。Cron Jobを活用することで、定期的なバックエンド処理やデータ更新などのタスクを簡単に自動化できます。

## #3 Vercelを利用したCron Jobの利用例
### #3-1 今回作成するサンプル
今回はサンプルとして、QiitaとZennのトレンド記事を収集してメールで送信する関数を作成します。
以下はGitHubのリポジトリです。
https://github.com/ryosuke-horie/vercel-cron-tech-trend

### #3-2 使用技術
以下を利用します。
- Next.js 13.4.1
- TypeScript
- Vercel

利用するライブラリ
- axios
- nodemailer
- dotenv

開発時に利用するAPI
- https://qiita-api.vercel.app/api/trend
- https://zenn-api.vercel.app/api/trendTech

### #3-3 Serverless Functionsの実装
APIを利用する部分とメール送信の部分は/lib以下に作成しました。APIをたたいてJSONからトレンド記事のタイトルとURLを取得し、メール送信するためのテキストに変換しています。
メール送信ではnodemailerを使用します。私はGmailを利用するので.envファイルにメールアドレスと認証用のパスワードを記載します。ここでは詳しく説明しないですが、Gmailのログイン用のパスワードではなく、Googleアカウントの設定から発行するものです。詳しく説明している記事がほかにあるので割愛させていただきます。

上記の関数を利用してトレンド記事についてGmailで送信するServerless Functionを作成します。/pages/api/cron.tsとしています。

```Typescript
import { NextApiRequest, NextApiResponse } from 'next';
import getQiitaTrend from '../../lib/qiita';
import getZennTrend from '../../lib/zenn';
import sendMail from '../../lib/send-main';

export default async function handler(
  request: NextApiRequest,
  response: NextApiResponse,
) {
    // メール送信用の文章を取得
    const QiitaText = getQiitaTrend()
    const ZennText  = getZennTrend()
    
    const mailBodyText = await QiitaText + await ZennText

    // メール送信処理
    return sendMail(mailBodyText)
}
```
### #3-4 デプロイ&動作確認
GitHubリポジトリを経由してVercelにデプロイします。デプロイする際、.envに設定した環境変数を忘れずにVercelで設定してください。
デプロイが成功したら、動作確認を行います。
[発行されたURL]/api/cron
をたたいて設定したメールアドレスにメールが送信されることを確認してください。

### #3-5 Cronを設定
プロジェクトのルートディレクトリに`vercel.json`を作成します。
```json
{
  "crons": [
    {
      "path": "/api/cron",
      "schedule": "* 13 * * *"
    }
  ]
}
```

pathにはserverless関数を作成したファイルへのパス、scheduleにはCronを設定します。サンプルでは毎日10時に行うように設定しています。

この変更をデプロイすればCronの設定の完了です。

### #3-7 Cron Jobsのテスト
Vercelのプロジェクトのページを開きメニューからsettingを選択します。
左側のメニューからCron Jobsをクリックして設定したCronを実行します。
今回の場合、自身の設定したメールに送信されていれば問題ありません。

![rapture_20230509073631.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/781232/5892a53d-3e30-46ae-3960-5a63fa731703.jpeg)

今回の場合、下のキャプチャのようなメールが送信されます。
![rapture_20230509073714.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/781232/092440fe-d2a9-c70a-a9b9-f60037494cfc.jpeg)


### #3-6 Cron Jobsについて補足
Vercelのhobbyプランでは２つのCronが一日１回利用できます。そのため`vercel.json`のscheduleに`* * * * *`を設定するとデプロイ時にエラーが発生します。

## #4 まとめ
VercelでのCron Jobの設定について記載させていただきました。結構制限が多いですが、デプロイがかなり簡単で利用しやすい印象です。
以前同様の関数をAWSのLambdaで実装したことがありますが、Vercelでの実装に比べて手間が非常に多く、またデプロイが難しかったので簡単な処理をCronで実装したかったらVercelを利用するのが非常に簡単なように思えます。

## #5 参考
### vercel公式ドキュメント
https://vercel.com/docs/cron-jobs
https://vercel.com/docs/concepts/functions/serverless-functions/quickstart#create-a-serverless-function

### nodemailerに関して
https://dev.classmethod.jp/articles/nodemailer-gmail/
https://qiita.com/hshimo/items/ac599f5f25a3fa105ddd