Hexo 博客添加 RSS 订阅: 生成 atom.xml 并推到各个平台
前言
写博客有个绕不开的问题: 读者怎么知道你有更新?
静态博客不像公众号那样有推送, 靠的是 RSS 订阅。但很多 Hexo 博客装好之后就没管过 RSS, 结果是:
- 搜索引擎抓不到新文章(虽然有 sitemap 兜底, 但覆盖率不如 RSS)
- 读者只能手动收藏首页
- 想订阅 RSS 的朋友发现没有
atom.xml, 直接放弃
这篇记录 Hexo 博客接入 RSS 的完整流程。
原理: RSS 是什么
先说清楚原理, 后面的操作就好理解了。
RSS 本质上就是一个 XML 文件, 里面按时间顺序列着你最新的文章:
1 |
|
订阅者用阅读器(Feedly、Inoreader、RSSHub 等)定时拉取这个文件, 有新文章就推送。
关键点: RSS 文件是一个静态文件, 每次 hexo g 构建时自动重新生成。 不需要额外服务, 也不需要数据库。
第一步: 安装 feed 插件
Hexo 官方没有内置 RSS 支持, 需要装插件:
1 | npm install hexo-generator-feed --save |
装完会自动生成 atom.xml(和可选的 rss.xml)。
验证是否生效
1 | hexo g |
然后检查 public/ 目录:
1 | ls public/*.xml |
应该能看到 atom.xml 和 rss.xml。构建完不生成 XML, 就是插件没装上或者没启用。
本文写作时踩过一个坑: 习惯性写
hexo clean && hexo g, 结果hexo clean在 Windows 上卡了十几分钟没删完。原因是hexo-fs删目录时对所有文件发起无限并发的删除调用, 文件一多句柄就排队假死。文件多的话直接手动删更快:
1 rm -rf public db.json && hexo g89 秒 vs 卡到没下文, 差别很大。
第二步: 配置输出
在 _config.yml 里加配置:
1 | feed: |
各字段含义:
| 配置项 | 说明 | 建议值 |
|---|---|---|
type |
输出格式, atom 或 rss2 |
见下 |
path |
输出文件名 | 与 type 一一对应 |
icon |
订阅图标 | 图标要能被订阅源客户端直接拉到 |
limit |
保留最近多少篇文章 | 20 |
order_by |
排序字段, -date 是最新在前 |
-date |
autodiscovery |
自动在 <head> 注入 <link rel="alternate"> |
true |
limit别设太大。RSS 里塞几百篇全文, 拉取一次就好几 MB, 阅读器体验很差。20 篇左右最舒服。
⚠️
type只认atom和rss2两个值。 写rss会被插件静默过滤掉 —— 不报错, 但rss.xml就是不生成。想同时输出两种格式,type和path都得写成数组:
1 | feed: |
如果数组长度对不上(比如 type 写了两个但 path 只写一个), 插件会自动补齐, 但还是老实写全比较好。
关于 atom 还是 rss
简单说:
- Atom —— 格式更规范, 支持全文和摘要两种模式, 主流阅读器都支持
- RSS 2.0 —— 更老但更通用的格式, 兼容性好一些
建议两个都生成。Atom 给现代阅读器, RSS 2.0 兜住那些只认老格式的工具。两种格式指向同一批内容, 不会造成重复收录。
第三步: 在 Butterfly 中加订阅按钮
光生成 XML 还不够, 得让读者知道入口在哪。
Butterfly 自带的方案: 没有
先说个坑。Butterfly 5.x 主题里根本没有 RSS 按钮这个配置项 —— 不是默认关闭, 是主题源码里压根没有。你在 _config.butterfly.yml 里写:
1 | rss: |
在 5.2.2 上是纯无效配置, 页面不会多出任何东西, 而且不会有任何报错提示你。网上很多教程(包括本文最初写的版本)都在讲这个 rss: 块, 但那是更早的版本或者别的分支。
验证方法很简单, 直接搜主题源码:
1 | grep -rn "rss" themes/butterfly/layout/ themes/butterfly/scripts/ |
搜不到就是真没有。别浪费时间在配置上找。
零成本方案: 侧边栏社交图标
改主题模板之前, 先试试这个 —— Butterfly 的侧边栏头像下面有一排社交图标(GitHub、Email 那些), 那个位置固定在侧栏顶部, 每一页都在, 曝光比文章底部高得多。
它由 _config.butterfly.yml 的 social 配置驱动, 加一行就行, 不用碰任何主题文件:
1 | social: |
格式是 图标类名: 链接 || 悬停提示 || 颜色, 三个部分都可以省。
主题的渲染源码在 themes/butterfly/layout/includes/header/social.pug, 一共就 8 行:
1 | each url, icon in theme.social |
几个细节:
| 写法 | 说明 |
|---|---|
fas fa-rss |
图标类名。fas 是 Font Awesome 的实心风格前缀, 别写成 fa-rss(不生效) |
/atom.xml |
相对站点根目录写。走 url_for() 处理, 部署到子目录也不会错 |
RSS订阅 |
鼠标悬停时的 title 提示 |
'#ee802f' |
图标颜色(可选)。不写就继承主题默认色, 跟其他社交图标保持一致 |
颜色那一段是可选的, 建议直接省略。侧边栏就那么几个图标, 一个是橙的另外两个是灰的反而显得跳。想跟整个站的主题色统一, 让它继承
--font-color就行。真要单独指定颜色, 引号必须保留 —— 少了会被 YAML 解析成别的类型, 颜色就静默丢了。
想同时给 RSS 2.0 留个入口? 再加一行指向
/rss.xml就行, 两个图标并排。不过一般一个就够, 阅读器都认 Atom。
这个方案我认为是性价比最高的: 零代码改动、主题升级不受影响、全站每页都显示。改主题模板那种方案留给需要自定义样式的情况。
更醒目的订阅入口
文章底部再放一个按钮, 转化率会更高。先说清楚 inject 的位置限制。 Butterfly 5.x 的 inject 实际只有两个键:
| 位置 | 插入点 |
|---|---|
head |
所有页面的 <head> 里 |
bottom |
所有页面底部(</body> 前) |
没有 post-bottom 这样的文章级注入点。 网上教程里写的 inject.post-bottom 在这个版本不会被渲染。
所以想放在文章底部, 有两个办法:
办法一: 改主题模板(推荐)
在 themes/butterfly/layout/post.pug 里, 找到 include includes/post/post-copyright.pug 那一行(它在 .tag_share 之前), 在这两行之间插入:
1 | //- RSS 订阅入口 |
注意缩进是 4 个空格 —— 这段代码在 article#article-container 块内部, 顶格写会被 Pug 当成另一个块, 直接编译报错。
对应样式加到 source/css/ 下(比如 rss.css), 再在 _config.butterfly.yml 的 inject.head 里引一下:
1 | inject: |
source/css/ 下的文件会被原样拷贝到 public/css/, 所以这里用绝对路径 /css/rss.css 引用就行。
用 url_for('/atom.xml') 而不是写死 /atom.xml, 这样部署在子目录时也能正确指向。图标类名 fa-solid fa-rss 依赖主题加载的 Font Awesome(通过 asset.fontawesome 配置项), Butterfly 默认带 FA6, 直接能用。
办法二: 放首页
如果不想改主题, 可以用 inject.bottom 加一段 JS, 在文章页动态插入按钮:
1 | inject: |
注意 pjax: 上面这段只在首次加载时执行, 切换页面后按钮会消失。需要额外监听:
1 | document.addEventListener('pjax:complete', function () { /* 重新插入 */ }); |
所以还是办法一更省心。
这里的路径是站点根目录下的相对路径。如果你的博客部署在子目录, 需要改成
/子目录/atom.xml, 或者用url_for()自动处理。
第四步: 提交订阅源
生成好了就该让人订阅。以下平台的收录比较有效。
提交给阅读器服务
| 平台 | 地址 | 说明 |
|---|---|---|
| Feedly | feedly.com | 老牌阅读器, 提交后聚合全网源 |
| Inoreader | inoreader.com | 功能强, 免费版够用 |
| RSSHub | rsshub.app | 聚合各类网站源 |
| Feed43 | feed43.com | 免费, 自动发现新源 |
| FeedBurner | feedburner.com | 需 Google 账号 |
大部分平台的提交流程都是: 注册 → 填入你的 RSS 地址 → 验证。
提交给搜索引擎
RSS 对搜索引擎的价值在于加速收录。sitemap 告诉搜索引擎”这些页面存在”, RSS 则是”这些是新的”。
RSS 和主动推送是两种不同机制, 各有各的用处:
| 方式 | 原理 | 触发时机 |
|---|---|---|
hexo-generator-baidu-sitemap |
生成 baidusitemap.xml 提交给百度 |
手动在站长平台提交 |
hexo-baidu-url-submit |
构建后自动 POST 新 URL 到百度 | 每次 hexo deploy 自动推送 |
sitemap 是”定期汇报全站有哪些页面”, 主动推送是”新文章一发布就通知”。两者不冲突, 有条件的话两个都配。
如果你的站目前只配了 sitemap 生成(也就是只生成
baidusitemap.xml而没有自动推送), 那 RSS 作为另一种”告诉搜索引擎新内容”的途径, 同样有补充价值。
校验 RSS 是否有效
可以用在线工具检查:
- https://validator.w3.org/feed/ —— W3C 官方校验器
- https://www.rssboard.org/rss-validator —— 检查是否被主流阅读器识别
校验报错别忽略。 常见问题是 XML 里有非法字符(比如文章里写了 & 但没转义), 这会导致某些阅读器整个源都读不出来。
常见问题
生成的是 atom.xml, 但别人要 rss.xml
前面说了, type 可以传数组同时输出两个。
订阅源里没有新文章
按顺序排查:
- 重新构建, 确认 XML 里有新 entry
- 检查
feed.limit是不是太小(比如设成 1, 旧的被顶掉了) - 确认
public/atom.xml确实更新了 - 确认 CDN 缓存 —— 静态文件如果走了 CDN, 可能还在发旧版本
文章内容在订阅源里是乱码
先确认是真乱码还是显示问题。Atom 的规范格式要求 <?xml version="1.0" encoding="utf-8"?>, 插件生成时已经写死了 utf-8, 没有 charset 配置项可调。
所以如果你加了 charset: utf-8 却没效果 —— 因为这个配置项不存在, 加了也是被忽略。
真出现乱码, 查这两处:
- 文章源文件本身的编码是不是 UTF-8(GBK 存的中文站点很容易踩)
description字段里有没有非法字符 —— XML 里的&必须写成&, 直接放裸的会让整个订阅源解析失败
想让订阅源只显示摘要而不是全文
没有 excerpt 这个配置项(网上部分教程写错了)。控制全文还是摘要的开关叫 content, 默认 true(输出全文):
1 | feed: |
content: false 时, 每篇文章只输出摘要 —— 摘要优先取文章 front-matter 里的 description, 没有就取 excerpt, 都没有就截取正文前 content_limit 个字符(默认 140)。
想让摘要长一点:
1 | feed: |
全文订阅的好处是阅读器不跳转到你的站点, 体验好、也不会消耗你的服务器流量。摘要模式则相反, 能给站点导流。
两种都试试, 看看哪个数据好。
一个容易被忽略的点: RSS 也是 SEO 利器
前面提到 RSS 能加速收录, 这里展开说一下。
搜索引擎的爬虫会定期抓取你的 RSS。因为 RSS 里是纯文本 + 结构化的新文章链接, 比解析 HTML 页面高效得多。
而且 RSS 文件是静态的, 没有 JS 渲染的负担。百度对 JS 的处理能力本来就弱, RSS 相当于给它提供了一条不需要执行 JS 的抓取路径。
所以我的建议是:
- 务必开启 RSS
- 别忘了
autodiscovery: true—— 插件会自动往每个页面的<head>里插一条<link rel="alternate" type="application/atom+xml">, 浏览器的”订阅此页”和大部分阅读器的自动发现都靠它, 这是最省事也最有效的入口 robots.txt里指向 sitemap(RSS 是自动发现的, 不用单独写)- 保持 entry 的
updated字段准确 —— 很多搜索引擎会把它当作内容新鲜度的信号
小结
接入 RSS 其实是 5 分钟的事:
npm install hexo-generator-feed --save_config.yml配feed:段(type和path都写成数组, 注意是rss2不是rss)- 重新构建, 确认
public/atom.xml和public/rss.xml都生成了 - 侧边栏加 RSS 图标(
_config.butterfly.yml的social加一行, 零代码改动, 全页可见) - 想要更醒目的转化, 再改
themes/butterfly/layout/post.pug加文章底部按钮(主题本身不带 RSS 功能, 别去找rss:配置) - 提交到 Feedly / Inoreader 等平台
别小看这个文件。 它是静态博客里少数几个”让读者主动回访”的通道, 而且几乎没维护成本 —— 装一次插件, 之后每次构建自动更新。
最后提一个坑: 如果你的站点文件托管在对象存储/CDN 上, 不存在的文件可能不会返回 404,而是返回一个 200 的错误页(我们遇到的就是返回一张 16KB 的 JPEG 图片)。这种环境下, 别人提交你的 RSS 地址时, 对方会拿到图片而不是 XML, 直接判定订阅源无效。所以 RSS 上线后一定要自己 curl 一次, 确认拿回来的是
<?xml开头的真 XML。
参考链接:
💡 准备购买云服务器 / 域名来搭建或部署站点?
通过下面的链接下单,通常能领到新用户专属优惠,也能小额支持本站持续更新:
阿里云(返现) |
腾讯云 2核2G 99元/年 |
腾讯云 云产品特惠












