フロントエンド
このブログにsitemap, robots.txt, RSSなどを配置したいが、旧来のPagesRouterとAppRouterのドキュメントやブログが混ざっていてなかなかまとまった情報が無い。 もろもろ調べたところ以下の通りに対応するのが一番簡単そうだった。
この2つに関してはNextJSに予め組み込まれた関数が存在しているので、それを使うのが良さそう。
このサイトはnext export
して静的ファイルとしてホスティングしているのでトップページのlastModifiedはビルドした時刻になるはず。
普通にホスティングする際にはデータ取得部分がStaticかDynamicかによって挙動が変わってしまうので少し注意が必要になるかもしれない。(未検証)
import { MetadataRoute } from "next";
import { getSortedBlogList } from "../lib/blogs";
import * as cst from "../lib/const";
import urlJoin from "url-join";
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const records: MetadataRoute.Sitemap = [];
const blogs = await getSortedBlogList();
records.push({
url: cst.SITE_URL,
lastModified: new Date(),
});
blogs.map((blog) => {
records.push({
url: urlJoin(cst.SITE_URL, "blog", blog.slug),
lastModified: blog.date,
});
});
return records;
}
import { MetadataRoute } from "next";
import * as cst from "../lib/const";
import urlJoin from "url-join";
export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: "*",
allow: "/",
},
sitemap: urlJoin(cst.SITE_URL, "sitemap.xml"),
};
}
RSSの生成機能はNextJSの組み込みでは存在しないので自前で実装する必要がある。
XMLを生成する必要があるため通常のpage.tsxでレンダリングするのではなく、 route.tsを利用してカスタムリクエストハンドラを作成する。
このサイトを参考にして、 rss.xml/route.ts
というファイルを作成し以下のようなコードを記載する。
import Rss from "rss";
import { getSortedBlogList } from "@/lib/blogs";
import * as cst from "../../lib/const";
import urlJoin from "url-join";
export async function GET() {
const feed = new Rss({
title: cst.TITLE,
description: cst.DESCRIPTION,
feed_url: urlJoin(cst.SITE_URL, "rss.xml"),
site_url: cst.SITE_URL,
language: "ja",
});
const blogList = await getSortedBlogList();
blogList.forEach((blog) => {
feed.item({
title: blog.title,
description: blog.summary,
url: urlJoin(cst.SITE_URL, "blog", blog.slug),
date: blog.date,
});
});
return new Response(feed.xml(), {
headers: {
"Content-Type": "application/xml",
},
});
}