Next.js
でサイトマップを作る方法を探してみたけど、情報が全然出てこなかったので見つけた情報をつなぎ合わせてサイトマップを自動作成します。
sitemap.xml
(サイトマップ)は検索エンジンにサイト内のクロールするWebページを教えるためのファイルです。なくても検索結果に出ないわけではないですが、現在だとあるに越したことはないくらいの印象。
サイトマップ、XMLファイルの作成
調べると記事一覧から xml
を作成する部分は見つかるので参考にします。
気になる部分を修正しつつ、記事一覧部分を仮作成してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
import { GetServerSideProps } from "next"; const origin = "https://narumium.net"; const getPosts = async () => { return [{ date: Date.now(), path: "/glsl" }]; }; type post = { date: number; path: string; }; const generateSitemap = (posts: post[], origin: string): string => { let xml: string = ""; posts.map((post) => { const date: string = new Date(post.date).toISOString().split("T")[0]; xml += `<url> <loc>${origin + post.path}</loc> <lastmod>${date}</lastmod> </url>`; }); return `<?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> ${xml} </urlset>`; }; export const getServerSideProps: GetServerSideProps = async ({ res }) => { const posts = await getPosts(); const sitemap: string = generateSitemap(posts, origin); res.setHeader("content-type", "application/xml; charset=utf-8"); res.write(sitemap); res.end(); return { props: {} }; }; const Sitemap = () => null; export default Sitemap; |
/sitemap.xml
にアクセスすると xml
が表示されるようになりました。
api/
でなく pages/
で res
から返すのは初なので違和感あります。
ページ一覧の取得
後は getPosts
でパス一覧とファイル最終変更日時を取るようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import fs from "fs"; const path2post = (dir: string, name: string) => { const stat = fs.statSync(`${dir}/${name}`); const path = (name == "index.tsx" ? dir : `${dir}/${name}`.replace(".tsx", "") ).replace("src/pages", ""); return { date: stat.mtimeMs, path }; }; const getPosts = (dir: string): post[] => fs .readdirSync(dir, { withFileTypes: true }) .flatMap((d) => d.isFile() ? !d.name.startsWith("_") && d.name.endsWith(".tsx") ? [path2post(dir, d.name)] : [] : getPosts(`${dir}/${d.name}`) ); |
若干複雑になりましたが、やってることは fs
の再帰探索とステータス取得です。
プロパティ 'flatMap' は型 'xxxx[]' に存在しません。ts(2339)
と怒られる場合は tsconfig.json
の compilerOptions.lib[]
に "es2019"
を追加してください。
flatMap
が定義されてない可能性があります。
Module not found: Can't resolve 'fs'
の場合は package.json
に追記。
1 2 3 |
"browser": { "fs": false } |
クライアント(ブラウザ)側で fs
が解決できなくなっている状態です。
Dynamic Routes
[dir]
や [file].tsx
などの名前でダイナミックルーティングしている場合、この方法では自動で細かいサイトマップの作成が出来ません。
getStaticPaths
で SSG
している場合は、手動で頑張ったり専用のサイトマップを作って robots.txt
に追記したりする必要がありそうです。
robots.txt
サイトマップの場所をクローラに教えるためのファイルです。
ルート直下に置けばいいので public/robots.txt
として作成します。
1 2 3 4 |
User-agent: * Allow: /* Disallow: /api/* Sitemap: https://narumium.net/sitemap.xml |
Sitemapを複数に分ける場合は Sitemap: xxxx
行を下に追加すればいいです。