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

next-feed-rss-atom

はじめに

ブログを購読していただくために便利な RSS と Atom のフィード情報を生成する方法を紹介します。
Next.js 向けにカスタマイズされたパッケージは現状で見つからないため、Node.js 向けのパッケージである feed を今回は利用します。
前回の記事 Next.js に next-sitemap を導入して超手軽にサイトマップ sitemap.xml を生成しよう でサイトマップを生成する方法を紹介していましたが、この記事ほどパッケージを導入してすぐ完了とはいきませんでした。
多少手間がかかりますが、この記事通り進めていただければスムーズに進められると思います。

成果物

以下のような3つのファイルが生成されることを目標とします。
/rss/feed.xml
feed_xml
/rss/atom.xml
atom_xml
/rss/feed.json
feed_json

feed を採用した理由

Next.js で RSS や Atom のフィード情報を生成する場合の情報を調査したときに、Zenn を開発されている @catnose さんのこちらの記事がとても参考になりました。
こちらの記事では rss というパッケージを利用されており、こちらは Node.js の RSS 生成系ではメジャーなようでしたが、最新の更新が4年前でした。
それに対して、以下の参考記事で紹介されたいた feed というパッケージが更新日も4ヶ月前と比較的新しくメンテナンスもされているようでしたので、今回はこちらの feed を採用することにしました。
npm_feed
rssfeed の Weekly Downloads を見ると feed の方が少し多い程度です。

バージョン情報

  • Node.js:15.11.0
  • React:17.0.2
  • Next.js:10.2.2
  • feed:4.2.2
  • marked:2.0.5

feed を導入

feed のインストール

以下のコマンドで簡単にインストールができます。
# npm の場合 npm install --save-dev feed # yarn の場合 yarn add --dev feed
また、Markdown のファイルを利用している時はフィード情報作成時に HTML ファイルへ変換する必要があるため、marked などのパッケージも利用します。
# npm の場合 npm install --save-dev marked # yarn の場合 yarn add --dev marked

フィード情報を集約する関数

以下のようにフィード情報を集約する関数 generatedRssFeed を作成しました。
process.env で環境変数から情報を取得しており、これらは .env ファイル内で定義しています。
// src/lib/feed.ts import fs from 'fs'; import { Feed } from 'feed'; import marked from 'marked'; function generatedRssFeed(): void { const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || ''; const date = new Date(); // author の情報を書き換える const author = { name: 'sample', email: 'sample@sample.com', link: 'https://...com', }; // デフォルトになる feed の情報 const feed = new Feed({ title: process.env.NEXT_PUBLIC_BASE_NAME || '', description: process.env.NEXT_PUBLIC_BASE_DISC, id: baseUrl, link: baseUrl, language: 'ja', image: `${baseUrl}/favicon.png`, // image には OGP 画像でなくファビコンを指定 copyright: `All rights reserved ${date.getFullYear()}, ${author.name}`, updated: date, feedLinks: { rss2: `${baseUrl}/rss/feed.xml`, json: `${baseUrl}/rss/feed.json`, atom: `${baseUrl}/rss/atom.xml`, }, author: author, }); // ローカルファイルや API 経由などでファイルのデータを取得する関数を書く const posts = getPosts(...); // feed で定義した情報から各記事での変更点を宣言 posts.forEach((post) => { // post のプロパティ情報は使用しているオブジェクトの形式に合わせる const url = `${baseUrl}/${post.id}`; feed.addItem({ title: post.title, description: post.description, id: url, link: url, content: marked(post.content), // marked で markdown => html date: new Date(post.date), }); }); // フィード情報を public/rss 配下にディレクトリを作って保存 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 generatedRssFeed;
上記のファイルに編集が必要な点をコメントで書いておきました。
必要な情報は基本的に揃っているため、post の形式などを合わせていただく程度で大丈夫です。
ここで、image に指定するファビコンに関して注意点があります。
通常、ファビコンは favicon.ico といった形式で保存しますが、RSS フィードの形式が正しいか確認するために W3C Feed Validation Service(https://validator.w3.org/feed/) を利用して確認すると、以下のような警告いが表示されます。
favicon
ファビコンを含めた画像では png, jpeg, gif といった形式の必要性があるらしく、RSS フィード用の画像はこれらのフォーマットを使用しておくことをお勧めします。
fwywd では RSS フィード用だけに png 形式のファビコン画像を用意しています。

ビルド時にフィード情報を自動的に更新

フィード情報を生成する generatedRssFeed という関数を作成し、こちらを SSG のビルド時に利用するためには以下のようにトップページの getStaticProps で実行すると良いでしょう。
// src/pages/index.tsx // ... export const getStaticProps: GetStaticProps = async () => { // フィード情報の生成 generatedRssFeed(); // ... return { props: { ... } }; };
SSR の場合は Next.js で動的に RSS フィードを生成する の記事を参考に src/pages/feed.tsxgetServerSideProps で実行すると良いみたいです。

動作確認

ローカルでのテストは yarn dev でサーバーを立ち上げ、localhost:3000/ のページへアクセス後、以下3つのページが生成されているか確認してみましょう。
/rss/feed.xml
feed_xml
/rss/atom.xml
atom_xml
/rss/feed.json
feed_json
これで動作確認が完了しました。
補足:URL が localhost:3000 となっている問題はローカル用の環境変数を使っているためであり、本番環境ではドメインが反映されるように私の手元では .env.development.env.production に分けています。

Git の対象外に設定しておこう

ローカル環境で開発を行うと、自動的に3つのファイルが生成されてしまい、これが Git の管理対象になるとコンフリクトを起こしたり、レビューの邪魔をします。
以下のように管理の対象外として設定しておきましょう。
# .gitignore ... # rss feed /public/rss/atom.xml /public/rss/feed.json /public/rss/feed.xml ...
SEO 対策として Google エンジンの流入をスムーズにするために生成した rss/feed.xmlrss/atom.xmlGoogle Search Console へ登録しておくことをオススメします。
google_search_console

おわりに

RSS は読んでもらうための一工夫

超お手軽とまではいきませんが、feed を利用することで RSS や Atom のフィード情報を反映することができました。
最近では Slack へ RSS フィードの設定もできるようになっており、技術チームではこれを使って日々最新の情報をキャッチアップすることも多いので、余裕があれば設定しておくことをオススメします。
株式会社キカガク 代表取締役会長
吉崎 亮介
twitter: @yoshizaki_91