みなさんこんにちは!
今回はNuxt3がそろそろ正式リリース(10/25)が近づいてきたので、
自作ブログリリースに向けて、サイトマップを作っていきたいと思います!
サイトマップ(sitemap.xml)とは
サイトマップを作ろうとしていたが、ふとこんな疑問を持ってしまった。
「なんでサイトマップ作るんだっけ?」
作った方がSEO的に良いという話は聞いたことがあるが、
そもそも論としてはわかっていなかった気がする。
なので、多少なりともサイトマップについて調べてみた。
Sitemaps(サイトマップ)標準は、ウェブマスターがサーチエンジンに、サイト内でクロールすべきURLを教えるための方式を規定するものである。サイトマップは、当該サイトにおけるURL全てをリストした、XMLファイルとして提供し、ウェブサイト運営者は各URLに付加的情報として、最終更新日時や更新頻度、他のURLとの相対的な重要度を加えたりできる。Sitemapsに対応したサーチエンジンでは、この情報を使って、サイトのクロールをより効率的に行えるようになる。サイトマップはサーチエンジンへのURL追加規約であり、URL排除規約であるrobots.txtを補完するものである。 https://ja.wikipedia.org/wiki/Sitemaps
なるほど!
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')
}
});
})
})
},
})
「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サポートが対応したら、書き換えようかなとは思っています。
それではまた次回の記事でお会いしましょう!