あらすじ
前任者から引き継いだ Nuxt3 + Jamstack 構成の Web コンテンツサイトの/sitemap.xml
を生成する API がものすごくボトルネックになってた
下記のような構成で
-
GET /api/sitemap.xml
にアクセスされるたびに、全件データベース検索を実行しsitemap.xmlとして整形し毎回生成して返してた。
コンテンツがカテゴリによって数万件あるので、これでは、リクエストからレスポンスまでものすごく遅くSEOよくない。
それに、特に認証機構を設けてないのでここを狙われると終わります。
改善方法
プリレンダリングしておくのも考えたが、下記のような便利な機能を発見
つ \defineCachedEventHandler
//
Nuxt 3 には defineCachedEventHandler
という便利なものがあります。
これは API レスポンスをキャッシュし、アクセス時に設定したTTLないではキャッシュを使用するので高速に返すことができます。
さらに swr: true
(stale-while-revalidate)オプションを使うことで、キャッシュされた古いデータを返しつつ、裏で非同期で新しいデータを取得してキャッシュを更新することができます。
実装例
// /server/api/sitemap.xml.ts
export default defineCachedEventHandler(async (event) => {
const items = await getSitemapItemsFromDB() // DBからsitemap用のデータ取得
const xml = generateSitemapXML(items)
return new Response(xml, {
headers: {
'Content-Type': 'application/xml',
},
})
}, {
swr: true,
maxAge: 60 * 60 * 24, // 24時間キャッシュ(ここは運用面で調整)
})
運用上の工夫ポイント
1. maxAge
の調整
- コンテンツを1日に数件更新 →
60 * 60 * 24
(24時間)で十分 - 数時間以内に sitemap を反映させたい →
60 * 60 * 6
(6時間)などに調整
🚀 結果どうなったか?
- sitemap API のレスポンスタイムが大幅改善!
- 爆速でレスポンスを返すように
📌 まとめ
構成 | 内容 |
---|---|
使用パッケージ | Nuxt 3 (defineCachedEventHandler ) |
キャッシュ戦略 |
swr: true + maxAge 指定 |
更新の柔軟性 | キャッシュ削除で即時反映も可能 |
最適なユースケース | Jamstack構成でのSEO対応 |
そもそも何万件もあるようなコンテンツを全件検索し動的再生して返すような作りはイケてないので、作りを変えてく予定です。
Jamstack のような構成では、"静的 + 動的のバランス" を取ることが非常に重要です。defineCachedEventHandler
のようなキャッシュAPIは、そのバランスを取るうえで強力な武器になります。
ぜひ活用してみてください💪