最終確認日

Supabase+Next.jsで動的にsitemap.xmlを生成する

概要

オンデマンドISRで作られたブログのインデックスが全くされないのでサイトマップ載せ異性を追加してみる。

環境

参考

実装手順

  1. Supabase クライアントを設定
  2. app/sitemap.xml/route.ts を作成
  3. robots.txt にサイトマップを追加

実装

Supabase のクライアントを登録しておく

これは後々 Vercel側にも登録しておいてね。

.env.localに追加。

.env.local
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your-service-role-key
NEXT_PUBLIC_SITE_URL=https://yourdomain.com

src/app/sitemap.xml/route.ts を作成

src/app/sitemap.xml/routes.ts

日本語が含まれるURLの場合は encode が必要。

/src/app/sitemap.xml/routes.ts
import { supabase } from "@/libs/supabase";

export async function GET() {
    const { data: posts, error } = await supabase
        .from("articles")
        .select("category, slug, updated_at")
        .eq("private", false);

    if (error || !posts) {
        console.error("Failed to fetch posts for sitemap:", error);
        return new Response("Failed to generate sitemap", { status: 500 });
    }

    const baseUrl = process.env.NEXT_PUBLIC_SITE_URL!;
    const urls = posts
        .map((post) => {
            // 日本語が含まれる場合はencodeが必要.
            const encodedSlug = encodeURIComponent(post.slug);
            const location = `${baseUrl}/${post.category}/${encodedSlug}`;
            const lastModified = new Date(post.updated_at || new Date()).toISOString();
            return `<url><loc>${location}</loc><lastmod>${lastModified}</lastmod></url>`;
        })
        .join("\n");

    const xml = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${urls}
</urlset>`;

    return new Response(xml, {
        headers: {
            "Content-Type": "application/xml",
        },
    });
}

Supabaseのクライアントは次のようにしている。

app/libs/supabase.ts
import { createClient } from "@supabase/supabase-js";

// 環境変数から取得
const SUPABASE_URL = process.env.SUPABASE_URL;
const SUPABASE_KEY = process.env.SUPABASE_KEY;

export const SUPABASE_IMAGE_BUCKET = process.env.SUPABASE_IMAGE_BUCKET;

if (!SUPABASE_URL || !SUPABASE_KEY || !SUPABASE_IMAGE_BUCKET) {
  throw new Error("Missing Supabase credentials. Check your environment variables.");
}

export const supabase = createClient(SUPABASE_URL, SUPABASE_KEY);

robots.txt にサイトマップを追加

User-agent: *
Allow: /

Sitemap: https://yourdomain.com/sitemap.xml

本番環境にデプロイ後

本番環境にデプロイしたらhttps://yourdomain.com/sitemap.xmlを確認する。

  • https://yourdomain.com/sitemap.xml にアクセスすれば、リアルタイムで sitemap を取得できる
  • Google Search Console にサイトマップのURL を登録する。
    • これで記事追加のたびに自動でクロール対象になるはず。

デプロイ後すぐにやっても「取得できませんでした」になっちゃった。

Supabase+Next.jsで動的にsitemap.xmlを生成する-1753807475989

数日してもダメみたい!!!!一度サイトマップの削除をする。

Supabase+Next.jsで動的にsitemap.xmlを生成する-1753928901985

そいで登録し直したけど変わらず。

かなり時間がかかるよう。

Search ConsoleでのXMLサイトマップ「取得できませんでした・読み込めませんでした」エラーの正体 の記事より

(著者訳)新しいサーチコンソールでの「読み込めませんでした」の表示はサーチコンソール側のバグ。実際の裏側ステータスでは「ペンディング」(保留中)になっていますよ! Sitemap could not be read in new GSC - Google Search Central Community ということで、Search Consoleにおける表示バグのようです。

読み込みませんでしたは「保留中」の意味でいいらしい。

こちらのXMLサイトマップ「取得できませんでした・読み込めませんでした」エラーの発生から3〜4ヶ月程度を経過した頃に、ふと思い出して確認しに行ったところ、正常に「成功」のステータスとなっていました。

3〜4ヶ月!!!!長い!!!

ということでとりあえずこのまま放置!登録されたら追記する。

おわりに

Next.jsのブログ記事がインデックスされない理由を調査した結果、とりあえずサイトマップを作ることにしたわけだが、効果の方は後ほど。

インデックスしてくれ〜〜〜〜〜〜〜〜!

おまけ: Firefox のエラーは関係なし

生成された XMLが悪いのかと思って調査していた時に遭遇したエラーについて。

sitemap.xml を Firefox の Developer Tools で見るとエラーが出ている。

XML パースエラー: 整形式になっていません。
URL: 
行番号: 7, 列番号: 61:

Supabase+Next.jsで動的にsitemap.xmlを生成する-1753931428763

cmd+U で該当箇所を見てエンコードを変えてみてもダメだったので超簡略化してみてみることに。

export async function GET() {
    const xml = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url><loc>https://example.com/test</loc><lastmod>2025-01-01T00:00:00Z</lastmod></url>
</urlset>`;

    return new Response(xml, {
        headers: {
            "Content-Type": "application/xml; charset=utf-8",
        },
    });
}

で、これでも同じエラーが出ている。Firefox のエラー???

他の人のサイトを見てきても同様のエラーが出てるのでこれは無視してokそう。

サイトアイコン
公開日
更新日