前回 に引き続き、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の値をキャッシュしていることが原因です。
確かに親切なのですが、ときに値をキャッシュして欲しくないAPIもあるかと思います。
そんな時は、どうすれば良いのか調べてみました。
⭕️ 対策 ❶ Vercel Functionsを使う
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 を使う
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;
❌ 対策 ❸ レスポンスにヘッダーをつける
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にする方法でキャッシュをクリアしました。