ブログ一覧に戻る

Nuxt3でサイトマップを作ってみた!

Nuxt3Vue3NuxtVueJavaScript

みなさんこんにちは!
イザナギです!

Sitemaps(サイトマップ)標準は、ウェブマスターがサーチエンジンに、サイト内でクロールすべきURLを教えるための方式を規定するものである。サイトマップは、当該サイトにおけるURL全てをリストした、XMLファイルとして提供し、ウェブサイト運営者は各URLに付加的情報として、最終更新日時や更新頻度、他のURLとの相対的な重要度を加えたりできる。Sitemapsに対応したサーチエンジンでは、この情報を使って、サイトのクロールをより効率的に行えるようになる。サイトマップはサーチエンジンへのURL追加規約であり、URL排除規約であるrobots.txtを補完するものである。 https://ja.wikipedia.org/wiki/Sitemaps

import { mkdirSync, writeFileSync, copyFile } from 'fs'
import { Readable } from 'stream'
import { dirname } from 'path'
import { SitemapStream, streamToPromise } from 'sitemap'
import { defineNuxtModule, createResolver } from '@nuxt/kit'

// https://github.com/benoitdemaegdt/nuxt3-sitemap
export default defineNuxtModule({
    meta: {
        name: 'sitemap',
        version: '0.0.1',
        configKey: 'sitemap',
        compatibility: { nuxt: '^3.0.0-rc.12' },
    },
    defaults: {
        hostname: 'http://localhost:3000',
    },
    async setup(options, nuxt) {
        async function generateSitemap(routes) {
            const sitemapRoutes = routes.map((route) => route.path)

            // https://github.com/ekalinin/sitemap.js#generate-a-one-time-sitemap-from-a-list-of-urls
            const stream = new SitemapStream({ hostname: options.hostname })
            return streamToPromise(Readable.from(sitemapRoutes).pipe(stream)).then(
                (data) => data.toString()
            )
        }

        function createSitemapFile(sitemap, filepath) {
            const dirPath = dirname(filepath)
            mkdirSync(dirPath, { recursive: true })
            writeFileSync(filepath, sitemap)
        }

        const resolver = createResolver(import.meta.url)
        const filePath = resolver.resolve(
            nuxt.options.srcDir,
            'node_modules/.cache/.sitemap/sitemap.xml'
        )

        nuxt.options.nitro.publicAssets = nuxt.options.nitro.publicAssets || []
        nuxt.options.nitro.publicAssets.push({
            baseURL: '/',
            dir: dirname(filePath),
        })

        nuxt.hook('nitro:build:before', (nitro) => {
            const paths = []
            const EXCLUDED_KEYWORDS = ['/api/_content', '_payload.js', '200.html']
            nitro.hooks.hook('prerender:route', (route) => {
                const shouldBeAddedToSitemap = EXCLUDED_KEYWORDS.every(
                    (excludedKeyword) => !route.route.includes(excludedKeyword)
                )
                if (shouldBeAddedToSitemap) {
                    paths.push({ path: route.route })
                }
            })
            nitro.hooks.hook('close', async () => {
                const sitemap = await generateSitemap(paths)
                createSitemapFile(sitemap, filePath)

                const outptFilepath = resolver.resolve(
                    nuxt.options.srcDir,
                    '.output/public/sitemap.xml'
                )

                copyFile(filePath, outptFilepath, (err) => {
                    if (err) {
                        console.log('sitemap.xml No created')
                        console.log(err)
                    } else {
                        console.log('sitemap.xml created')
                    }
                });
            })
        })
    },
})

「copyFile」を使用し、「.output/public/sitemap.xml」のファイルを「node_modules/.cache/.sitemap/sitemap.xml」の内容に更新(上書きコピー)するように修正しただけです。
私が試したところ、修正後のコードでは、1回目の「yarn generate」時にも「.output/public/sitemap.xml」が作られるようになっていました!

まとめ

今回はNuxt3でサイトマップを作成する方法を紹介いたしました。
nuxt/sitemap」がNuxt3で使えれば使ったのですが、まだ対応していないようでしたので、
違うコードを利用しての実装となりました。
nuxt/sitemap」のNuxt3サポートが対応したら、書き換えようかなとは思っています。

それではまた次回の記事でお会いしましょう!

関連記事

この記事に関連するおすすめです。