なるほど!
GoolgeなどのサーチエンジンにクロールすべきURLを教えることも、サイトマップを設置する目的の一つらしいです。
確かに、「Google Search Console」を利用するときはサイトマップを登録しますね。
さらに「priority」タグを使うことで、URLの重要度も追加できるとのこと!
これは知らなかった。
Nuxt3でサイトマップを作る
サイトマップについて、軽く調査し終えたところで、
早速、サイトマップを作っていこう!
とりあえずNuxtでサイトマップといえば「nuxt/sitemap」だと思うが、
制作している現在は、まだサポートしていないみたいだった。
https://github.com/nuxt-community/sitemap-module/issues/246
なので、自作で作るしかないかな?と思いネットを漁っていたら下記のようなサイトを見つけた。
https://github.com/benoitdemaegdt/nuxt3-sitemap
何!?SSG作成時にも対応しているだと!
これは試すしかない!
「yarn generate」を2回打たないとsitemapが反映しなかった
こちらのサイトの「Setup for a dynamic site powered by @nuxt/content with prerendering」項目の手順を参考に実装したが、
1回目の「yarn generate」時には、サイトマップが作成されなかった。
なぜだろう?
理由は下記URLに記載のようでした。
https://github.com/benoitdemaegdt/nuxt3-sitemap/issues/9
どうやら、「.cache」フォルダ内サイトマップを作成していない状態で「yarn generate」を実行すると、
「.output/public」内にサイトマップが作成されないみたい。
2回目の「yarn generate」を実行すると、以前の「.cache」フォルダ内サイトマップが参照され、
「.output/public」内にサイトマップが作成されるみたいだな。
「yarn generate」を一回で済ませる方法の案
ではどうするか?
私は単純に「sitemap.ts」を、下記のようにコードを修正することで対応しました。
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')
}
});
})
})
},
})