ウェブ系Nuxtブログ

Nuxt + Contentful のブログにFeedを追加する方法【Markdown対応】

最近InoreaderというRSSリーダーで情報収集をするようになり、自分のブログもフィードに対応させたいと思うようになりました。
そこでこの記事では、"@nuxtjs/feed"を使ってブログの更新情報をフィードで提供する手順を紹介します。

使用するプラグインのインストール

まず、今回使用するプラグイン @nuxtjs/feedをインストールします。

$ npm install @nuxtjs/feed

nuxt.config.jsのmodulesに追加します。

modules: [
    '@nuxtjs/feed' // 追加
],

そして、nuxt.config.jsにfeedの設定を記入するセクションを追加します。

modules: [
    '@nuxtjs/feed'
],
// ここから追加
feed: [
  //  この中に設定を記述していく
]

Feedの設定

Contentfulから記事一覧を取得するために、~/plugins/contentfulを読み込みます。
nuxt.config.jsの最初のほうに次の行を追加します。

const client = require("./plugins/contentful");

feedの設定項目を記述していきます。

まず、フィードを書きだすURLを相対パスで設定します。
一般的には、"/feed", "/feed/", "/feed.xml"などが多いようです。

feed: [
  {
    path: '/feed' // 追加
  }
]

次に、フィードに記事の一覧が登録されるように設定していきます。
当ブログの設定を例として紹介しますので、適宜書き換えて参考にしてください!

feed: [
  {
    path: '/feed',
    // ここから追加
    async create(feed) {
      feed.options = {
        title: "イズミログ",
        link: "https://izm51.com/feed", // 上のpathで設定したものと対応するように
        description: "イズミログ - フィード"
      };
      // 記事を取得
      await client
        .getEntries({
          content_type: "post",
          order: "-sys.createdAt"
        })
        .then(entries => {
          entries.items.forEach(post => {
            feed.addItem({
              title: post.fields.title,
              id: `https://izm51.com/posts/${post.fields.slug}/`, // 記事のURL
              link: `https://izm51.com/posts/${post.fields.slug}/`, // 記事のURL
              description: post.fields.description,
              content: post.fields.content,
              date: post.fields.update ? new Date(post.fields.update) : new Date(post.sys.createdAt), // 記事の最終更新日
              published: new Date(post.sys.createdAt), // 記事の公開日
            });
          });
          feed.addCategory("blog");
          feed.addContributor({
            name: "Izm51",
            link: "https://izm51.com/"
          });
        });
    },
  }
]

dateについて補足しますと、このブログではContentfulのContent modelにupdateという日付型の入力欄を設置し、記事を修正したときに手動で書き換える形式にしています。
ちょっとした修正だけで毎回最終更新日を更新したくないため、このようにしています。

最後に、cacheTimeとフィードのタイプを設定します。

feed: [
  {
    path: '/feed',
    async create(feed) { /* 略 */ },
    // ここから追加
    cacheTime: 1000 * 60 * 15,
    type: "atom1"
  }
]

フィードのタイプは"rss2", "atom1", "json1"の3種類が設定できます。
これらのタイプとはフィードの規格のことですが、"rss2"か"atom1"に設定しておけばたいていのRSSリーダに対応しているかと思います。

MarkdownをHTMLに展開する

ここまでで一応フィードの設定は完了ですが、このままでは記事の内容がMarkdown形式のまま配信されてしまいます。
そこで、markdown-itで記事内容ををHTML形式に展開してから登録するように設定していきます。

nuxt.config.jsの最初の方に次の一行を追加して、markdown-itを読み込みます。

import MarkdownIt from 'markdown-it';

feedのcreateの中で、markdown-itを使用するための準備をしておきます。

    async create(feed) {
      feed.options = {
        // 略
      };
          
      // 追加
      const md = new MarkdownIt({
        html: true,
        typography: true,
      })

feed.addItemの部分で、記事の内容をmarkdown-itでHTMLにレンダリングしたものをcontentに登録するように設定します。

            feed.addItem({
              // 略
              content: md.render(post.fields.content), // 変更

記事内にある画像とは別にサムネイル画像を設定している場合は、このように記事の最初に画像を挿入してしまうのもおすすめです。

content: `<img src="https:${post.fields.image.fields.file.url}?w=1080">` + md.render(post.fields.content),

まとめ

最終的な完成版は次のようになりました。

feed: [
  {
    path: '/feed',
    async create(feed) {
      feed.options = {
        title: "イズミログ",
        link: "https://izm51.com/feed",
        description: "イズミログ - フィード"
      };
          
      const md = new MarkdownIt({
        html: true,
        typography: true,
      })
      
      await client
        .getEntries({
          content_type: "post",
          order: "-sys.createdAt"
        })
        .then(entries => {
          entries.items.forEach(post => {
            feed.addItem({
              title: post.fields.title,
              id: `https://izm51.com/posts/${post.fields.slug}/`,
              link: `https://izm51.com/posts/${post.fields.slug}/`,
              description: post.fields.description,
              content: `<img src="https:${post.fields.image.fields.file.url}?w=1080">` + md.render(post.fields.content),
              date: post.fields.update ? new Date(post.fields.update) : new Date(post.sys.createdAt),
              published: new Date(post.sys.createdAt),
            });
          });
          feed.addCategory("blog");
          feed.addContributor({
            name: "Izm51",
            link: "https://izm51.com/"
          });
        });
    },
    cacheTime: 1000 * 60 * 15,
    type: "atom1"
  }
]

$ npm run generateすることでフィードが生成されるようにできました!
あとはトップページなどにフィードへのリンクを追加すれば設定完了です。

これで、普段使用しているRSSリーダーでも自分のブログが見られるようになりました!
https://izm51.com/feed

ではまた。


【参考】
generate時にエラーが出たときの対処
javascript - TypeError: Cannot add module namespace property '_nuxtConfigFile' to nuxt.config.js with NUXT 2.4.5 - Stack Overflow

nuxt.config.jsmodule.exports = {}export default { } に変更する


コメント欄 ご意見、ご感想お気軽に!間違いなどあれば、ご指摘お願いいたします!