我的博客程序是用 next.js 写的,之前一直没有做订阅功能,今天晚上心血来潮,整了一整。
这里借助的是 feed 这个 package.
yarn add feed
在 pages 下面创建一个 feed.xml.js 的文件。
// ...
import { Feed } from "feed"
const Page = () => {}
export async function getServerSideProps(context) {
const res = context.res
if (!res) {
return
}
const posts = await getRecentPosts(1)
const feed = createFeed(posts)
res.setHeader("Content-Type", "text/xml")
res.write(feed.rss2())
res.end()
return {
props: {}
}
}
export default Page
这里是需要 getServerSideProps
来服务端渲染这个 xml 格式的响应内容,另外两点需要注意的是
- 你需要 export 一个空的
Page
, 不然请求会报错 - 需要设置
Content-Type
为text/html
, 然后通过res.write
生成的 xml 写入 response body. getServerSideProps
需要返回一个空的props
, 不然会有一个 warning
createFeed 方法的实现如下
const createFeed = posts => {
const siteURL = "https://anl.gg"
const date = new Date()
const author = {
name: "greatghoul",
email: "greatghoul@gmail.com",
link: "https://github.com/greatghoul",
}
const feed = new Feed({
title: "Ask and Learn",
description: "greatghoul 的博客,记录开发心得,分享有趣的应用和服务",
id: siteURL,
link: siteURL,
favicon: `${siteURL}/favicon.ico`,
copyright: `All rights reserved ${date.getFullYear()}, greatghoul`,
updated: date,
feedLinks: {
rss2: `${siteURL}/feed.xml`
},
author
})
posts.forEach((post) => {
const url = `${siteURL}/posts/${post.id}`
feed.addItem({
title: post.title,
id: url,
link: url,
description: post.brief,
content: post.content,
author: [author],
contributor: [author],
date: new Date(post.published_at),
})
})
return feed
}
其实 feed 这个 package 除了 rss2,还支持其他格式,详见官方文档
console.log(feed.rss2());
// Output: RSS 2.0
console.log(feed.atom1());
// Output: Atom 1.0
console.log(feed.json1());
// Output: JSON Feed 1.0
上面这些做好后,我们还是只能通过 url 来访问 feed,你可能还需要添加页面链接以及 head link.
<a href="/feed.xml">FEED</a>
<Head>
<link rel="alternate" type="application/rss+xml" title="Feed for Ask and Learn" href="/feed.xml" />
</Head>