Nuxt.jsでxmlファイルを返す(動的にRSSフィードを作成する)方法になります。
nuxt/sitemapやnuxtjs/feedなどのサイトマップやRSSフィード用のライブラリはありますが、今回は使用しません。
nuxtjs/feedでもRSSフィードのxmlファイルを作成できますが、apiなどで動的に情報を書き換えるのは不向きだった為です。
RSSフィードの生成をする
RSSフィードの生成には、feedというライブラリを使用しました。
npm install feed
yarn add feed
ページのasyncDataやmiddlewareでxmlを返すとエラーになる
page/demo
<script lang="ts">
import Vue from 'vue'
import { Feed } from 'feed'
export default Vue.extend({
async asyncData({ res, $axios }) {
if (process.server) {
try {
const feed: any = new Feed({
title: 'タイトル',
description: '説明文',
id: 'http://example.com/',
link: 'http://example.com/',
language: 'ja',
favicon: 'http://example.com/favicon.ico',
copyright: 'All rights reserved 2021',
updated: new Date(2021, 2, 14),
generator: 'awesome'
})
const posts = await $axios.get('https://demo.jp')
if (posts) {
posts.data.forEach((post) => {
feed.addItem({
title: post.title,
id: post.id,
link: post.link,
description: post.description,
image: post.image
})
})
}
feed.addCategory('demo')
feed.addContributor({
name: 'demo',
email: 'info@demo.jp',
link: 'https://demo/'
})
res.setHeader('Content-Type', 'application/xml')
return res.end(feed.rss2())
} catch (error) {
console.log(error)
}
}
}
})
</script>
/demo
にアクセスすると、xml(RSSフィード)が表示されます。
しかし、下記エラーが出てしまいます。
Cannot set headers after they are sent to the client
詳しくは分からないのですが、
node_modules/@nuxt/server/dist/server.js
で、クライアント側へ既にレスポンスを返却しているからだと思われます。
serverMiddlewareを使ってxmlファイルを返すようにする
Nuxt.jsのserverMiddlewareを使ってxmlファイルを返すようにしました。
nuxt.config.js
serverMiddleware: [{ path: '/api', handler: '@/server/index.ts' }]
nuxt.config.js
に上記の設定を追加します。
server
ディレクトリを作成して、index.tsファイルを追加します。
server/index.ts
import express, { Response } from 'express'
import axios from 'axios'
import { Feed } from 'feed'
const app = express()
app.get('/feed', (res: Response) => {
try {
const feed: any = new Feed({
title: 'タイトル',
description: '説明文',
// 同様なので省略
})
const posts = await axios.get('https://demo')
if (posts) {
posts.data.forEach((post) => {
feed.addItem({
title: post.title,
// 同様なので省略
})
})
}
feed.addCategory('demo')
feed.addContributor({
name: 'demo',
// 同様なので省略
})
res.setHeader('Content-Type', 'application/xml')
return res.end(feed.rss2())
} catch (error) {
res.status(400).json({
status: 'failed',
message: error.message
})
}
})
export default app
/api/feed
にアクセスすると、無事にエラー無くxml(RSSフィード)が表示されました。