Next.jsでfeedライブラリを使いRSSフィードを生成する

RSSフィードの実装についてです。

## ライブラリ選定
今回はXML生成として[feed](https://www.npmjs.com/package/feed)というnpmライブラリを使用しました。
似たようなライブラリで[rss](https://www.npmjs.com/package/rss)というものもありましたが、更新が５年前より止まっていたので
個人的にデモやドキュメントが見やすい、型で書かれてるのもありfeedを選びました。
issueやPRに対してのサポート面はどちらもさほど変わりないかなといった印象です。

## 実装方法

### feedのインストール
以下のコマンドでインストールします。
```ts
//npm の場合
npm install feed

//yarn の場合
yarn add feed
```

### フィード情報を作る関数
``` ts:lib/feed.ts
import { Feed } from 'feed';

export const generateRssFeed = async (): Promise<string> => {
  //環境変数など任意のリンクをbaseUrlに入れる。
  const baseUrl ='localhost:3000'
  const feed = new Feed({
    title: '会社名',
    description:
      '概要',
    id:baseUrl,
    link:baseUrl,
    language: 'ja',
    copyright: 'copyright',
    generator: baseUrl,
  });

 //データをとってくる。API経由やファイル経由を想定
 const posts = await getPosts();
//各記事をフィードに追加
  posts.forEach((post) => {
    feed.addItem({
      title: post.title,
      description:post.description,
      date: new Date(post.date),
      id: post.url,
      link: post.url,
    });
  });
　
// Output: RSS 2.0
  return feed.rss2();

//今回はxmlの生成ですが、atomやjsonファイルでの生成も可能です。
//feed.atom1()でatomファイル生成
//feed.json1()でjsonのファイル生成
};
```

### xmlファイルを生成する
データの生成からレスポンスまで`getServerSideProps`の中で行います。
```ts:pages/feed.tsx
import { generateRssFeed } from '@/lib/feed';
import type { GetServerSideProps } from 'next';

export const getServerSideProps: GetServerSideProps = async ({ res }) => {
  const xml = await generateRssFeed();
  res.statusCode = 200;
  res.setHeader('Cache-Control', 's-maxage=86400, stale-while-revalidate'); // 24時間キャッシュする
  res.setHeader('Content-Type', 'text/xml');
  res.end(xml);

  return {
    props: {},
  };
};
const Page = (): null => null;
export default Page;

```


## ローカル環境での確認方法

localhost:3000/feed.xmlにアクセスし、期待しているフィードが生成されているか確認。
例として、
```
<rss version="2.0">
<channel>
<title>会社名</title>
<link>http://localhost:3000</link>
<description>概要です。</description>
<lastBuildDate>Mon, 09 May 2022 10:06:19 GMT</lastBuildDate>
<docs>https://validator.w3.org/feed/docs/rss2.html</docs>
<generator>http://localhost:3000</generator>
<language>ja</language>
<copyright>　copyrightの内容￥</copyright>
<item>
<title>
<![CDATA[ リンク ]]>
</title>
<link>http://localhost:3000/該当リンク先</link>
<guid>http://localhost:3000/該当リンク先</guid>
<pubDate>Tue, 26 Apr 2022 01:29:54 GMT</pubDate>
<description>
<![CDATA[ >概要が入ります]>
</description>
</item>
.
.
.

```
上記のようなファイルが生成されていればokです。
ローカル環境での確認のためリンクはlocalhost:3000になっていますが、確認環境（検証や本番）によりURLは異なります。

https://validator.w3.org/feed/
で正常に生成できているか確認してもokです。

## 本番環境での確認方法
### ファイル生成を確認
https://validator.w3.org/feed/ でファイル生成が正常か確認します。
URLの判定でも生成されたファイルをコピペして判定してもOKです。Congratsが出たら生成確認としています。

### Google Search Consoleに登録
SEO対策として、管理アカウントからGoogle Search consoleに登録も行います。
新規記事が公開されたことをGoogleに伝えます。
この登録をしないと、記事が公開されてもGoogleは認識してくれないので...

また、一度登録して終わりではなく頻繁に更新する必要があります。
手動で毎日更新するのは面倒なので、Github Actionsに任せる手もあるようです。[参考記事](https://fwywd.com/tech/ping-sitemap-to-google)

### RSSリーダーで読み取れるか確認
feedly等rssリーダーを使い記事の表示を確認します。

## 参考記事
[Next.jsで動的にRSSフィードを生成する](https://zenn.dev/catnose99/articles/c7754ba6e4adac)
[Google Search Console へのサイトマップの更新通知を GitHub Actions で定期実行しよう](https://fwywd.com/tech/ping-sitemap-to-google)