Ключевые особенности
| Language | C# |
| Framework | .NET 9 |
| Project type | Библиотека |
| Status | Активная разработка |
| License | MIT |
| Nuget |
|
| Downloads |
|
| Github | Laraue.CmsBackend |
Как родился проект
Нам хотелось хранить все статьи в формате markdown. Желательно, отдельно от фронтенд части. С воможностью поиска, фильтраций по атрибутам и всего, что только прийдет в голову. Существующие варианты - это либо хранение markdown во фронтенд части, либо полноценные CMS с хранением контента в базах. Хотелось иметь свой вариант, объединяющий это все. И чтобы фронтенд оставался реактивным приложением, на котором можно написать что угодно.
Что такое CMS
CMS, или система управления контентом — это программа, которая позволяет пользователям создавать, управлять и изменять содержимое веб-сайта без специальных технических знаний. Образцами таких программ являются WordPress, Drupal и Joomla.
Почему CMS не всегда является лучшим подходом
Использование CMS помогает сэкономить пользователям массу усилий:
- Отпадает необходимость думать об архитектуре системы.
- Пользователи часто могут выбирать из бесплатных шаблонов, избегая необходимости писать код с нуля.
- Многие аспекты уже продуманы: от SEO до панелей администратора и многого другого.
Это значительно сокращает время вывода приложения в продуктивную среду. Однако у CMS-решений есть и недостатки, которые делают их неподходящими для некоторых ситуаций:
- Архитектурные ограничения: Они навязывают конкретную архитектуру, которая не всегда идеальна. Некоторые проекты требуют глубокой кастомизации, которую может быть сложно или невозможно реализовать в рамках CMS.
- Несоотвествие стеку компании: Технологический стек CMS не всегда соответствует остальной инфраструктуре компании, что приводит к дополнительным затратам на поддержку.
- Риски безопасности: Популярность CMS-платформ делает их главными целями для атакующих, которые используют известные уязвимости для кражи баз данных, подмены веб-сайтов или использования их в вредоносных целях.
CMS и реактивные фреймворки
Что такое реактивные фреймворки?
Реактивные фреймворки — это инструменты разработки ПО, которые ставят во главу угла создание пользовательских интерфейсов, быстро реагирующих на изменения и обновления, часто в реальном времени. Они достигают этого путём автоматического обновления интерфейса при изменении нижележащих данных, что даёт более плавный и интерактивный пользовательский опыт. Они предлагают такие преимущества, как:
- Более быстрая и простая разработка.
- Упрощённое сопровождение кода.
Однако ключевая проблема сайтов, построенных с использованием реактивных фреймворков, заключается в том, что полная HTML-страница может не отображаться до тех пор, пока страница не начнёт загружаться. Хотя пользователь это может не всегда замечать, это может быть проблематично для поисковых роботов. Им может потребоваться выполнить JavaScript, дождаться XHR-запросов и обработать значительный объём данных, прежде чем финальное содержимое страницы станет доступно для индексации. Хотя современные роботы всё лучше обрабатывают такие кейсы, подобные страницы все равно проигрывают в индексации классическим вариантам.
Как улучшить SEO при работе с реактивными фреймворками
Существует два основных метода решения этой проблемы:
- Серверный рендеринг (SSR): Сервер выполняет JavaScript и возвращает полностью отрендеренную HTML-страницу. Это улучшает SEO и может повысить производительность для пользователей с медленными устройствами, так как они избегают начальной фазы рендеринга JavaScript. Однако во многих случаях преимущества перевешиваются возросшей нагрузкой на сервер. Поскольку большинство устройств способны эффективно обрабатывать рендеринг JavaScript, серверный рендеринг часто лишь увеличивает время загрузки. Хотя это может облегчить жизнь роботам, это может ухудшить опыт для обычных пользователей.
- Генераторы статических сайтов (SSG): Этот подход генерирует содержимое страниц Vue и выдаёт статический сайт с поддержкой JavaScript. Это интересная концепция, но она имеет ограничения в отношении кастомизации и использования компонентов и лучше всего подходит для действительно статических сайтов. Отображение динамического контента может быть сложным или невозможным.
Технические требования для этого блога
После исследования возможных решений для блога стало ясно несколько требований:
- Фронтенд блога должен быть достаточно гибким, чтобы реализовать любую идею без ограничений, налагаемых архитектурой конкретной библиотеки.
- Содержимое страниц должно загружаться как можно быстрее, чтобы улучшить показатели SEO.
- Подход с использованием Markdown-файлов был особенно привлекателен, так как эти файлы можно хранить в Git для контроля версий, что устраняет необходимость в базе данных.
Видение библиотеки
Учитывая необходимость полной гибкости фронтенда, возможность загружать конкретные статьи через API являлось ключевым требованием.
Основные требования к бэкенд-библиотеке:
- Возможность структурировать Markdown-файлы и управлять ими.
- Поддержка front matter для хранения атрибутов.
-
Определённые типы контента, например,
Articleкоторый должен включать обязательное свойствоstring Tags[]. Это не позволяет авторам случайно упускать необходимую информацию, обеспечивая корректную работу бэкенда. - API для получения файлов, фильтрации, сортировки или возврата определённого содержимого, например, списка уникальных тегов из всех статей, отсортированных по алфавиту.
Как использовать получившуюся библиотеку
Для использования необходимо определить типы контента, которые будут на сайте. Например:
public class Article : BaseContentType
{
public required string[] Projects { get; init; }
public required string Description { get; init; }
}
Далее, нужно написать контент. Например, article1.md:
---
title: О моем проекте
projects: [Проект 1, Проект 2]
description: Мое короткое описание
---
Контент статьи
Рекомендуется делать организацию файлов, соотвествующую структуре на frontend.
- blog
- articles
- article1.md
- article2.md
Теперь можно создать API для запроса контента:
var cmsBackend = new CmsBackendBuilder(new MarkdownParser(new MarkdownToHtmlTransformer(), new ArticleInnerLinksGenerator()), new MarkdownProcessor())
.AddContentType<Article>()
.AddContentFolder("blog")
.Build();
И использовать его в контроллерах:
[ApiController]
[Route("api/blog")]
public class BlogController(ICmsBackend cmsBackend) : ControllerBase
{
[HttpPost("single")]
public Dictionary<string, object> Get([FromBody] GetEntityRequest request)
{
return cmsBackend.GetEntity(request);
}
[HttpPost("list")]
public IShortPaginatedResult<Dictionary<string, object>> Get([FromBody] GetEntitiesRequest request)
{
return cmsBackend.GetEntities(request);
}
}
Теперь фронтенд может вызывать бэкенд и запрашивать только те данные, которые ему нужны. Конечно, эндпоинты можно определить статически, при этом каждый эндпоинт соответствует конкретному DTO и действию. В качестве альтернативы, HTML может генерироваться на бэкенде с использованием MVC-контроллеров. Основной принцип заключается в том, что бэкенд CMS предоставляет API для получения Markdown-файлов и их свойств. Всё остальное — это решение пользователя.
Сложные моменты при реализации
Будут описаны в отдельных статьях:
- Написание интерпретатора для Markdown из-за отсутсвия подходящей библиотеки с лицензией MIT
Хронология
- Сен 2025 Исследование существующих CMS для выбор решения для блога.
- Окт 2025 Первая версия CMS Backend.
Дальнейшие идеи
-
Система может быть не только бэкендом для фронтенда, но также иметь опции для автопостинга контента куда-то еще. Например, пакет
Laraue.CmsBackend.Telegramмог бы содержать инструменты для запуска бота, который мог бы постить содержимое статей в каналы по заданным критериям.