🗺️

【Nuxt3】SSGモードでxmlサイトマップを作成する方法【動的ページ対応】

2023/06/25に公開

今回は、Nuxt3 でxmlサイトマップを作成していきたいと思います。

巷で紹介されている方法は、/server/routes/sitemap.xml.tsを作成するなど様々ありますが、それらは、動的ページを補足するのにそれぞれのライブラリごとでAPI呼び出しを行うなど、少し回りくどい実装となっており、皆さんもサイトマップ作成には苦労されているのではないでしょうか。

今回は、Nuxt3で静的サイト作成をする際に使える、(たぶん)全ページを補足できるxmlサイトマップの作成方法を見つけたので載っけておきます。

動作保証はありませんので自己責任でお試し下さい。

完成品

結論がほしい方向け

0. 動作確認バージョン

  • Nuxt: v3.6.0
  • Sitemap: v7.1.1

1. パッケージの追加

コマンドライン
# yarn
yarn add --dev sitemap

# npm
npm install --save-dev sitemap

# pnpm
pnpm add --dev sitemap

2. プログラム作成

/nuxt.config.ts
import genSitemap from './scripts/gen-sitemap';

export default defineNuxtConfig({
    // ...
    nitro: {
        hooks: {
            'compiled': genSitemap,
        }
    }
    // ...
})
/scripts/gen-sitemap.ts
import type { Nitro } from "nitropack";
import { SitemapStream, streamToPromise, SitemapItem } from 'sitemap';
import { Readable } from 'stream';
import { writeFileSync } from 'fs';
import path from 'path';

// サイトドメインを指定(最後スラッシュ不要)
const domain = "https://YOUR_DOMAIN";

export default async function genSitemap(nitro: Nitro) {
    if (!nitro._prerenderedRoutes) {
        return;
    }

    const publicDir = nitro.options.output.publicDir;

    const routes = nitro._prerenderedRoutes?.map((e) => e.fileName || null).filter((e, i, a) => e && a.indexOf(e) === i && e.endsWith("index.html")).map((e) => {
        return {
            url: e?.replace(/index\.html$/, ''),
	    
	    // この辺の値は各自調整して下さい
            changefreq: 'weekly',
            priority: .7,
        } as SitemapItem;
    });
    const smStream = new SitemapStream({ hostname: domain });
    Readable.from(routes).pipe(smStream);

    const data = await streamToPromise(smStream);

    writeFileSync(path.join(publicDir, 'sitemap.xml'), data.toString());
}

しくみ

Nuxt 3 の静的サイトは、Nitro のクローラーによって、サイト内がくまなく巡回された上で全ページが生成される仕組みとなっています。

今回はそれを利用して、ページのクロールが終了したタイミングでサイトマップ生成を発火し、クロールしたルートの一覧を Nitro から取得して、サイトマップを生成しています。

だから、ヘッドレスCMSのAPIを呼び出してルートを個別で生成し直す…なんてことをしなくとも、完全なサイトマップを作成できるのです。

ただし、この方法が SSR や クライアントサイド描画 の Nuxt で使えるかはわかりません(多分ムリ)。

なにかご意見・ご感想などあればコメント欄にお寄せくださいませ。

Discussion