Как создать RSS канал в Nuxt 3
Что такое RSS
Это файл в формате XML, который используется на сайтах для получения информации об обновлениях страниц и выходе новых статей. Формат читается в браузерах, а также в специальных нативных или онлайновых RSS читалках.
Я на всех своих сайтах подключаю RSS ленты и, несмотря на некий спад популярности этого формата, знаю многих людей, которые до сих пор им пользуется. Я тоже в их числе.
Подключаем RSS к Nuxt
Как всегда, хотелось магии, чтобы просто подключить и забыть, но в своих поисках не нашёл готовой рабочей библиотеки для Nuxt, поэтому решил использовать библиотеку node-rss
.
Из плюсов такого решения — можно легко настроить RSS под свои задачи. К примеру, добавить вторую ленту для альтернативного языка, или отфильтровать те страницы, которые в ленте не нужны.
Устанавливаем node-rss
.
npm i -D rss
И если в проекте используется TypeScript, как в моём случае, устанавливаем типы к нему.
npm i -D @types/rss
Конфигурация Nuxt
Для RSS ленты нам потребуется пререндер страницы. Поэтому в файле nuxt.config.ts
, в секции Nitro, прописываем маршрут для каждой ленты RSS на сайте.
export default defineNuxtConfig({
nitro: {
prerender: {
routes: ['/rss.xml'],
},
},
})
Создание статьи
Для того чтобы передавать информацию об обновлениях страниц в правильном формате, нам потребуется включить в текст каждой страницы метаданные в формате YAML, так называемый frontmatter. К примеру файл статьи /content/posts/1.my-article.md
может содержать следующие поля:
---
title: Заголовок статьи
description: подзаголовок статьи
createdAt: 2023-09-01
---
Конечно, frontmatter может содержать и другие данные, например, имя файла картинки, тема статьи, время прочтения и т.д., но именно поля заголовка, описания и дата создания необходимы для формирования валидной структуры ленты RSS.
Создание маршрута
Теперь создаём серверный маршрут для RSS ленты. Допустим URL для неё будет https://sitename.com/rss.xml
.
Добавляем в файл server/routes/rss.xml.ts
следующий код:
import { serverQueryContent } from '#content/server'
import RSS from 'rss'
interface RSSItem {
title: string
description: string
createdAt: string
_path: string
}
const hostname: string = 'sitename.com'
export default defineEventHandler(async (event) => {
const feed = new RSS({
title: 'Sitename',
description: 'RSS feed for this site',
site_url: hostname,
feed_url: `${hostname}/rss.xml`,
})
const docs = await serverQueryContent(event)
.sort({ createdAt: 1 })
.where({ _partial: false })
.locale('en')
.only(['title', 'description', 'createdAt', '_path'])
.find()
const posts = docs.filter((doc) => doc?._path?.includes('/posts'))
for (const post of posts as RSSItem[]) {
feed.item({
title: post.title ?? '-',
description: post.description,
date: post.createdAt,
url: `${hostname}${post._path}`,
})
}
const feedString = feed.xml({ indent: true })
event.node.res.setHeader('content-type', 'text/xml')
event.node.res.end(feedString)
})
Здесь мы используем асинхронную функцию serverQueryContent
для того, чтобы получить данные о существующих статьях. И там же указываем критерии для фильтрации (список всех опций фильтрации можно посмотреть в документации по ссылке в конце статьи).
В моём случае, я получаю только три поля из каждой статьи на английском языке в порядке возрастания даты.
Затем дополнительно отфильтровываю страницы по каталогу, в котором они находятся.
И в конце я добавляю данные в парсер библиотеки node-rss
, чтобы сформировать окончательный код страницы.
Проверка на валидность
После того как каналы RSS созданы, нужно обязательно их проверить на корректность с помощью онлайн валидатора. И конечно же загрузить ленту в любимый клиент RSS, чтобы окончательно удостовериться, что всё в порядке.
В итоге
На своём сайте я создал два RSS канала: один для английской, второй — для русской версии. Они находятся на разных адресах и различаются только фильтром по текущей локали .locale('en')
.
Для того чтобы фильтр локали в Nuxt Content работал, её нужно корректно настроить. Об этом я напишу в следующий раз.
Ссылки: