March Wednesday,2nd 2022: AM

Next.jsにRSSとsitemapを導入した

参考

Next.js に feed を導入して RSS と Atom のフィードを生成しよう

Generate RSS feeds for your static Next.js blog

Next.js に next-sitemap を導入して超手軽にサイトマップ sitemap.xml を生成しよう

next-sitemap公式GitHub

npm install feed

getStaticPropsを叩いてるページでその中で後述のfeed.tsをgenerateRssFeedとして呼び出す。

pages/Index.tsx

import generateRssFeed from "../libs/feed";

export const getStaticProps: GetStaticProps = async () => {
  await generateRssFeed();
  const data: EntryCollection<IPostFields> = await client.getEntries({
    content_type: "blog",
    order: "-fields.date",
    limit: 10,
  });
  return {
    props: {
      blog: data.items,
    },
  };
};

export default Index;

libs/feed.ts

import fs from "fs";
import { Feed } from "feed";
import client from "../libs/contentful";
import { EntryCollection } from "contentful";
import { IPostFields } from "../libs/types";

async function generateRssFeed() {
  const baseUrl = "https://sou-web.net";
  const date = new Date();
  const author = {
    name: "Sou Watanabe",
    email: "[email protected]",
    link: baseUrl,
  };

  const feed = new Feed({
    title: "sou-web.net",
    id: baseUrl,
    link: baseUrl,
    description: "Sou Watanabeのメモ兼用ウェブアプリケーション。",
    language: "ja",
    image: `${baseUrl}/images/logo.svg`,
    favicon: `${baseUrl}/favicon.ico`,
    copyright: `All rights reserved ${date.getFullYear()}, Sou Watanabe`,
    updated: date,
    generator: "Next.js using Feed for Node.js",
    feedLinks: {
      rss2: `${baseUrl}/rss/feed.xml`,
      json: `${baseUrl}/rss/feed.json`,
      atom: `${baseUrl}/rss/atom.xml`,
    },
    author,
  });

  const entries: EntryCollection<IPostFields> = await client.getEntries({
    content_type: "blog",
    order: "-fields.date",
    limit: 1000,
  });

  entries.items.forEach((blog) => {
    const url = `${baseUrl}/${`/docs/${blog.fields.slug}`}`;
    feed.addItem({
      title: blog.fields.title,
      id: url,
      link: url,
      description: blog.fields.description,
      date: new Date(blog.fields.date),
      author: [author],
    });
  });
  fs.mkdirSync("./public/rss", { recursive: true });
  fs.writeFileSync("./public/rss/feed.xml", feed.rss2());
  fs.writeFileSync("./public/rss/atom.xml", feed.atom1());
  fs.writeFileSync("./public/rss/feed.json", feed.json1());
}

export default generateRssFeed;

これでpublicにrssというフォルダが生成されその中にfeed.xmlとjson、atom.xmlが生成される。 fs.writeFileSyncはその通りにgetStaticPropsはgetServersidePropsと違って動的変更に弱いがこのfsが読み込んで同期処理でカバーしている。

npm install next-sitemap

プロジェクトディレクトリ直下にconfig.jsファイルを作成。

sitemap.config.js

module.exports = {
  siteUrl: "https://sou-web.net",
  generateRobotsTxt: true,
};

自分は最小限にしたかったのでこんな感じにした。

あとはpackage.jsonでビルド時にこれを走らせるように設定。

package.json

  "scripts": {
    "dev": "next dev",
    "build": "next build && next-sitemap --config sitemap.config.js",
    "start": "next start",
    "export": "next export",
    "lint": "next lint"
  },

buildに && next-sitemap --config sitemap.config.js"を追加。

&&は左辺も右辺もtrueの時にtrueという命令。

これでpublicにrobots.txtとsitemap.xmlとsitemap-0.xmlが生成される。 sitemap-0というのは本の区切りみたいなもので一定の収録を終えたら次のsitemap-1が生成される。

RSSとsitemapってなに?

RSSはフィードとしてGoogleReederなどに昔からあった機能で、登録しておくと更新が見れるようになっています。なのでリーダーアプリなどで見たいブログを登録して置いて更新したときだけ通知で見るようにする使い方が一般的です。

sitemapはGoogle Search Consoleに登録することによって検索キーワードを分析したりできます。

ブログやWEBサイトには必須の機能だと思うのでよかったら導入してみてください。