Задача: Сделать универсальный рендеринг и маршрутизацию Concepts
Сделать универсальный рендеринг и маршрутизацию Concepts
Минимизировать число специализированных шаблонов: основная публикационная механика сайта должна работать поверх универсальной сущности Concept.
Цель
Построить публичный слой haih-cms вокруг универсальной сущности Concept вместо отдельной инфраструктуры для каждого legacy-типа контента.
Что сделать
- Реализовать универсальный маршрут и базовый renderer Concept.
- Использовать
name,description,intro,content, URI и общесистемные атрибуты как основной контракт страницы. - Специализированные представления добавлять только там, где они дают реальную пользовательскую ценность, а не потому, что в legacy существовала отдельная таблица.
- Обеспечить единые правила навигации, SEO, внутренних ссылок и отображения контента.
- Поддержать AI-generated и AI-updated content без изменений schema и renderer-а.
Результат
Новые типы содержательных объектов можно публиковать как Concepts без создания нового CRUD, отдельной таблицы и отдельного рендера по умолчанию.
Ворклоги
Assets Proxy Middleware для legacy-ассетов
В новой реализации добавлен middleware для обслуживания статических файлов legacy-сайта по пути /assets/.
Исходная проблема
Rails Asset Pipeline исторически разрешал ссылки на ассеты не напрямую по физическому расположению файла, а через собственный механизм поиска и manifest. В результате фактические файлы могут находиться в разных подкаталогах, тогда как HTML и CSS продолжают ссылаться на них через упрощённые пути.
На практике обнаружены как минимум следующие варианты хранения:
shared/assets/— основные ассеты;shared/assets/stylesheets/— CSS и связанные файлы;shared/assets/stylesheets/fonts/— шрифты.
При этом клиентские ссылки могут выглядеть как /assets/filename.css или относительные url(font.woff2) без указания реального подкаталога. В старом Rails-приложении это скрывалось логикой Asset Pipeline.
Реализованное решение
Добавлен middleware server/middleware/assetsProxy.ts, который перехватывает запросы к /assets/ и последовательно ищет запрошенный файл в нескольких известных legacy-каталогах.
Порядок поиска:
shared/assets/shared/assets/stylesheets/shared/assets/stylesheets/fonts/
Клиенту отдаётся первый найденный подходящий файл. Таким образом новая система воспроизводит необходимую часть поведения Rails Asset Pipeline без переноса самого pipeline.
Безопасность
В middleware предусмотрены базовые ограничения против выхода за пределы каталога ассетов:
- блокируются пути с
..; - блокируются двоеточия в пути;
- после нормализации проверяется, что resolved path остаётся внутри
shared/assets/.
Значение для миграции
Это решение позволяет корректно отображать legacy-страницы и стили во время переходного периода без ручного переписывания большого количества исторических ссылок на ассеты. При этом compatibility-логика изолирована в одном месте и не проникает в основную модель данных или маршрутизацию haih-cms.
Дальнейшая проверка
- проверить корректные MIME-типы для CSS, JS, шрифтов и изображений;
- проверить cache headers;
- проверить поведение при совпадающих именах файлов в нескольких каталогах;
- убедиться, что middleware не позволяет читать файлы вне разрешённого дерева;
- по мере нормализации ассетов решить, нужен ли proxy как постоянный слой или только как миграционная совместимость.
Корректировка архитектуры публичного слоя
После решения унифицировать содержательные данные вокруг Concept задача рендеринга также упрощается: не требуется автоматически воспроизводить отдельный шаблон под каждый legacy-тип сущности. Базовым должен стать универсальный renderer Concept, а специализированные представления добавляются только при реальной пользовательской необходимости.
Это уменьшает количество кода, который должен сопровождаться, и позволяет AI-generated/AI-updated content публиковаться через общий механизм.
Прогресс: публичный слой новой версии собран
Новый сайт уже фактически работает поверх новой архитектуры и универсального рендеринга. При переносе выяснилось, насколько дорого обходилась старая модель: у разных legacy-сущностей были собственные представления и во многих случаях отдельный CSS.
Полное восстановление визуального оформления всех внутренних страниц сознательно не выполнялось. Это означало бы дополнительную работу по воспроизведению старых специализированных шаблонов, которые затем всё равно пришлось бы переделывать при обновлении дизайна.
На текущем этапе достаточно функционально корректного и единообразного отображения контента. Следующая визуальная итерация должна строиться уже на новой общей модели, а не имитировать legacy-структуру.