Vercel Cron 定期更新博客

💡
我的博客使用 Next 开发,由 Notion 提供数据源, 部署在 Vercel 上。由于项目使用 API 在构建时获取数据,每次更新在 Notion 更新文章后,我都需要前往 Vercel 后台重新部署,以保证网站始终为最新的文章数据。这太麻烦了,我决定寻找一种简易的方式。本文有我评估后的两个方案可供选择。
  1. 生成一个 Vercel 部署 Hook,每次更新后手动去访问。
    在项目页,进入“设置”页面,然后选择“Git”菜单项。 在“Deploy Hooks”部分中,为 Deploy Hook 选择一个名称,并选择在请求生成的 URL 时将部署的分支。
  2. 结合 Vercel Cron 和 Vercel Deploy Hook, 实现定期检查 Notion 的数据更新并部署 (Vercel Free 版本 Cron 仅支持每天一次, 如需更高需求可使用 GitHub Actions)
🧑‍💻
pages/api/cron.ts

import type { NextApiRequest, NextApiResponse } from "next"
import { Client } from "@notionhq/client"
import { PostProps } from "@lib/types"
import redis from "@lib/redis"

const notion = new Client({
    auth: process.env.NOTION_API_TOKEN,
})

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
    try {
        const response = await notion.databases.query({
            database_id: process.env.POSTS_TABLE_ID,
        })
        const results = response.results as unknown as PostProps[]
        const latestTimestamp = results.reduce((latest, document) => {
            const timestamp = Date.parse(document.last_edited_time);
            return Math.max(latest, timestamp);
        }, 0);
        // 将最新的文档更新时间转换为日期对象
        const latestDate = new Date(latestTimestamp);

        const redisValue = await redis.get("latestCacheDate");
        // 将 Redis 中的值转换为日期对象
        const redisDate = new Date(redisValue);


        // console.log(latestDate,redisDate);

        // 比较 Redis 中的值与最新日期
        const isValidDate = (date) => date instanceof Date;
        let data = { "latestDate": latestDate, "data":{} }
        if ((isValidDate(redisDate) && isValidDate(latestDate) && (redisDate < latestDate)) || !isValidDate(redisDate)) {
            // 访问 Vercel Deploy Hook
            const result = await fetch(process.env.DEPLOY_HOOK_URL);
            // 更新Redis
            // console.log("Update Redis");
            await redis.set('latestCacheDate', latestDate.toUTCString());
            data = { "latestDate": latestDate, "data" : await result.json() }
        }
        res.status(200).json(data);
    }
    catch (error) {
        console.error('Error fetching exchange rate:', error);
        res.status(500).json({ error: 'Failed to fetch exchange rate' });
    }

}

export default handler

这将创建一个/api/cron路由, 每次访问该路由它都会检查文档的最新时间, 如果有更新则访问触发 Vercel 的部署 Hook。

要做到自动更新, 定期访问这个路由即可。Vercel Cron 和 GitHub Actions 都是不错的自动任务工具。

我这里使用了 Vercel Cron, Vercel Cron job 是基于时间的调度工具,用于自动执行重复任务。

只需要创建或更新您的 vercel.json 文件, Vercel cron 这将 每天凌晨 5 点(世界标准时间)运行。 如果需要更密集的运行任务, 你需要升级计划。

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