みかづきブログ・カスタム

基本的にはちょちょいのほいです。

ローカルで動作するNext.jsのAPIをVercelにデプロイすると同じ値しか返ってこなくなったので、値をキャッシュしないように設定した 💻

前回 に引き続き、Next.jsのlocalとVercelの挙動の違いについてです。

まずは、こちらのソースコードをご覧ください。

ソースコード

src/api/timestamp/route.ts

import { NextResponse } from 'next/server';

export async function GET(request: Request) {
  return NextResponse.json({
    timestamp: Date.now()
  });
}

単純に、Date.now()の値を返すだけのAPIです。
localhostで動作確認してみましょう。

リロードするたびにtimestampの値が更新されます。

では、こちらのAPIをVercelにデプロイして動作確認してみます。

https://vercel-api-prototype-git-cache-timestamp-kimizuka.vercel.app/api/timestamp

リロードしてもtimestampの値が更新されなくなりました。

原因

VercelがAPIの値をキャッシュしていることが原因です。

vercel.com

確かに親切なのですが、ときに値をキャッシュして欲しくないAPIもあるかと思います。
そんな時は、どうすれば良いのか調べてみました。

⭕️ 対策 ❶ Vercel Functionsを使う

vercel.com

https://vercel-api-prototype-git-cache-timestamp-with-edge-kimizuka.vercel.app/api/timestamp

runtimeをedgeにしつつ、レスポンスにヘッダーをつければ毎回更新されるようになりました。

src/api/timestamp/route.ts

import { NextResponse } from 'next/server';

export const runtime = 'edge';

export async function GET(request: Request) {
  return NextResponse.json({
    timestamp: Date.now()
  }, {
    status: 200,
    headers: {
      'Cache-Control': 'no-store',
      'CDN-Cache-Control': 'no-store',
      'Vercel-CDN-Cache-Control': 'no-store'
    }
  });
}

❌ 対策 ❷ vercel.json と next.config.js を使う

vercel.com

https://vercel-api-prototype-git-cache-timestamp-with-v-be7884-kimizuka.vercel.app/api/timestamp

ドキュメントの通り、vercel.json と next.config.js で設定してみたのですが、こちらはうまくいきませんでした。僕の理解が間違っているのかもしれません。

vercel.json

{
  "headers": [{
    "source": "/api/(.*)",
    "headers":[
      {
        "key" : "Cache-Control",
        "value" : "no-store"
      }
    ]
  }]
}

next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  async headers() {
    return [
      {
        source: '/about',
        headers: [
          {
            key: 'Cache-Control',
            value: 'no-store'
          }
        ]
      }
    ];
  }
};

module.exports = nextConfig;

❌ 対策 ❸ レスポンスにヘッダーをつける

vercel.com

https://vercel-api-prototype-git-cache-timestamp-with-header-kimizuka.vercel.app/api/timestamp

src/api/timestamp/route.ts

runtimeをedgeにせずに、レスポンスにヘッダーをつけても更新されるようになりませんでした。
ドキュメントをみるとこれでもうまくいきそうだと思ったのですが、僕の理解が間違っているのかもしれないです。

import { NextResponse } from 'next/server';

export async function GET(request: Request) {
  return NextResponse.json({
    timestamp: Date.now()
  }, {
    status: 200,
    headers: {
      'Cache-Control': 'no-store',
      'CDN-Cache-Control': 'no-store',
      'Vercel-CDN-Cache-Control': 'no-store'
    }
  });
}

⭕️ 対策 ❹ revalidateを0に設定する

https://vercel-api-prototype-git-cache-timestamp-with-r-f20b5d-kimizuka.vercel.app/api/timestamp

ドキュメントには記載がないのですが、revalidateを0に設定したらキャッシュされなくなりました。

import { NextResponse } from 'next/server';

export async function GET(request: Request) {
  return NextResponse.json({
    timestamp: Date.now()
  });
}

export const revalidate = 0;


以上です。
普通に考えると、Vercel Functionsを使うのが良いと思います。
しかし、Firebaseを使っているプロジェクトでruntimeをedgeにしてFirebaseと組み合わせてみたところ、いろいろ問題が起こったので、revalidateを0にする方法でキャッシュをクリアしました。