やりたいこと
私は、Tech Course Rankというランキングサイトを開発・運営しております。
ランキングのデータを、日次のバッチ処理でDBに更新しています。データが1日1回のみ更新されるので、ページ自体も1日1回だけDBからデータフェッチして、静的HTMLを生成しておけば、DBアクセスによる課金も減らせるし、ユーザーにも最新の情報を届けると思い、実装しました。ただ、静的HTMLの日次更新がうまくいかず、それについて共有させていただきます。
(本来は、DBのデータ更新のタイミングで、On-Demandでキャッシュの更新がしたいが、それもうまくいっていないので、後回し)
前置きとして、私はFirebaseを否定したり、批判をしたいわけではなく、個人開発でFirebase Hostingを使ってみて、純粋に困ってしまったので、共有しようと思っております。むしろ、助けを求めています。
テックスタック
項目名 | 採用した技術 |
---|---|
フレームワーク | Next.js |
ホスティングサービス | Firebase Hosting |
データベース | Firestore |
上記のやりたいことを実現するために、Next.jsでサポートされている、ISR(Incremental Static Regeneration)機能を利用しようと思いました。ざっくり説明すると、ビルド時に静的HTMLを作成しておきます。その上で、設定した秒数が経過するたびに、静的HTMLを更新する仕組みです。
問題は、Next.jsアプリをFirebase Hostingでホストすると、ISRが動作しない、ということです。ISR動きましたよ!みたいな記事も見ましたが、私2024年1月の時点では、本サイトでは期待した動作になっておりません。
検証方法
まずは、キャッシュ更新をする期間を設定しない状態で、デプロイします。
Cache Control Headerを確認すると、こうなります。
max-age=3600、と入ってますね。デフォルトの設定なんですかね。
次に、キャッシュ更新をする期間(revalidate)を設定します。試しに、60 * 5 = 300sec に設定しました。
再び、Cache Control Headerを確認します。
今度は、s-maxageが300秒と、stale-while-revalidateというディレクティブが表示されました。revalidateの設定が効いてそうですね。
問題
ただし、Firestore側のデータを更新した後、設定した5分以上経っても、ページ上の表示が更新されることはありませんでした。具体的には、Firestore側に保存しているデータ(ランキングデータの更新日)を2024/1/23などに変更しても、ページ側で更新されません。デプロイすると、ようやく適応されます。
ページ側の表示では最終更新日 = 2024/1/24 のまま
考察
考えられるのは、ISRの設定は動いてるが、Firebase側のCDNのキャッシュが残って、更新されていないとか。ただ、s-maxageが設定されているので、CDN側もキャッシュクリアされるはずなんだけど・・・。
いずれにしても、Firebase HostingにNext.jsをデプロイして、素直にrevalidateだけ設定しても、動作できませんでした。
おわりに...
改めて、私は、Firebaseを否定したり、批判をしたいわけではありません。Firebaseは、料金面も使いやすさもよく、愛用しています。
ただ、Firebase HostingでNext.jsのISRが動いたというブログは見つけましたが、さらっと「動きました」としか書いてないのでよく分からず。逆に、ISRはサポートしていない、というドキュメントも見つけられませんでした。私の検索能力の問題かもですが・・・。
色々試してうまくいかなかったので、近々Vercelに移行してみようと思います。VercelのPricingが、Firebaseより分かりにくく、若干不安ですが、これも個人開発の醍醐味ですね。やってみます。
長々とご清聴いただき、ありがとうございました。技術っぽいブログは初めて書くので、緊張しています。お手柔らかに、お願い致します。
本ブログで扱ったサイト(Tech Course Rank)について、こんなブログも書いていますので、ご興味があれば是非。