Разработка веб-приложений всё чаще ассоциируется с использованием фреймворков, которые призваны ускорить процесс создания и организовать структуры приложений. Однако автор проекта Croissant решился пойти по пути создания приложения без единого фреймворка, полагаясь исключительно на веб-стандарты и минималистичные решения. Croissant — это персональный RSS агрегатор, который разрабатывается в формате no-build без компиляции, минимизируя внешние зависимости и концентрируясь на простоте и эффективной работе с современными браузерами. Это одновременно вызов и поиск идеального компромисса между удобством разработки и производительностью конечного продукта. Начало работы над Croissant было спонтанным и вдохновляющим, без детальной проработки архитектуры или дизайна.
Такой подход позволил экспериментировать с функционалом, уделяя внимание деталям и небольшим дополнениям, вроде анимированных фавиконов и интерактивных эмодзи, которые делают взаимодействие с приложением более приятным и живым. Тем не менее, основной упор сделан на удобное чтение: открытие статей происходит в полноэкранном режиме, блокируя отвлекающие факторы и позволяя сосредоточиться на содержании. Важно отметить, что разработка велась с приоритетом темной темы, учитывая популярность и удобство ее использования в современных интерфейсах. Отклонение от классических много-колоночных RSS ридеров, которые из-за своего внешнего вида часто напоминают почтовые клиенты, было сознательным решением — Croissant стремится вытеснить эти шаблонные решения, предлагая новый подход к чтению. Особое внимание уделяется архитектуре без сборки: отсутствует этап компиляции, нет использования TypeScript или других подобных инструментов.
Вместо этого используется простой текстовый редактор и статический веб-сервер, который обслуживает index.html. В своей разработке автор применяет JSDoc-комментарии для эмуляции типизации и отслеживания потенциальных ошибок, хотя признается, что строгая типизация TypeScript всё же дает определенные преимущества. Одним из ключевых новшеств стала интеграция сервисного работника, который обеспечил локальное кэширование данных, что не только ускоряет загрузку, но и добавляет поддержку офлайн-доступа к приложению. Это очень важно для веб-приложений, работающих с динамическими данными, такими как RSS-ленты, поскольку позволяет снизить нагрузку на сервер и повысить надежность работы пользователя с контентом.
Для решения проблем с кросс-доменными запросами (CORS) был разработан прокси-сервер на базе Deno, который не только обрабатывает запросы, но и нормализует данные из различных форматов RSS, Atom и JSON в единую структуру. Такой подход обеспечивает гибкость и совместимость с разнообразными источниками данных — нелегкой задачей с учетом того, что спецификации часто трактуются неоднозначно или не соблюдаются в полном объеме авторами лент. Особое внимание уделено безопасности при работе с HTML из RSS лент. Web-приложения, получающие внешние данные, потенциально подвержены атакам типа межсайтового скриптинга (XSS). В Croissant решено было производить обработку и очистку HTML исключительно на стороне браузера, используя возможности встроенного DOM API.
Такой подход оказался эффективным и даже предпочтительным, поскольку браузерные парсеры гораздо совершеннее серверных в разборе HTML, а также позволяют избежать избыточного бэкенд-кода и сложных зависимостей. Важным элементом безопасной обработки стало использование элемента template для временного хранения разметки и установка свойства textContent вместо innerHTML при работе с непроверенным текстом. Использование textContent предотвращает исполнение нежелательных скриптов и стилизаций, которые могут негативно повлиять на интерфейс или безопасность. В то же время для сохранения семантики и форматирования в теле статей разработано рекурсивное очищение DOM, которое удаляет все теги и атрибуты, не входящие в заранее определённый список разрешённых. Используются дополнительные меры для обработки ссылок, медиаэлементов и таблиц с целью улучшения UX — например, добавление прокрутки для таблиц и управляющих элементов аудио и видео.
Весь этот процесс напоминает работу таких библиотек, как DOM Purify, но реализуется собственными средствами проекта, чтобы избежать избыточных зависимостей и соответствовать философии no-build. Важным наблюдением стало то, что разнообразие и недоработки HTML-разметки в RSS лентах требуют постоянного добавления новых кейсов для обработки и нормализации контента, в том числе исправления собственных ошибок в генерации данных. Croissant также обрабатывает различные варианты энкодинга HTML, включая CDATA секции и HTML-сущности, что позволяет корректно отображать контент независимо от особенностей исходного контента. Если в содержимом используется криптографическая сущность HTML полностью, она декодируется для формирования правильной структуры DOM, а в случае отображения видимого HTML применяется двойное кодирование. Для стилей в Croissant используется гибридный подход.
Комбинация декларативного Shadow DOM для постоянных элементов интерфейса и динамического Shadow DOM для элементов, создаваемых на лету, позволяет держать стили изолированными и избегать конфликтов. Работа с CSS осложняется ограничениями без использования сборки и необходимости использования импорта стилей. Было проведено несколько экспериментов с разными способами подключения стилей, включая inline-стили с импортом, динамическую загрузку CSS и использование adopted stylesheets — последних оказались наиболее эффективным вариантом, значительно уменьшая задержки при рендеринге и устраняя эффект быстрого вспышки неотформатированного содержимого (FOUC). Такой подход повышает производительность и улучшает визуальное восприятие приложения. В вопросах управления состоянием и реактивности Croissant пока находится в стадии экспериментов.
Отказавшись от тяжелых фреймворков в пользу кастомных элементов и нативных возможностей браузера, автор внедряет простой паттерн на основе пользовательских событий и глобального хранилища, основанного на Dexie — обертке IndexedDB. Такой выбор позволяет обходить сложные схемы передачи пропсов, которые в React порой приводят к избыточной сложности. События распространяются через DOM, обеспечивая коммуникацию компонентов без громоздких решений и позволяя сохранять принципы инкапсуляции и независимости. Интерес к новым API, таким как Preact Signals и предложениям TC39 по нативной реактивности, показывает открытую позицию к инновациям и стремление со временем ещё больше упростить приложение без потерь в функциональности. При этом проект признает, что такие фреймворки, как Svelte, по-прежнему очень удобны для более сложных и интерактивных пользовательских интерфейсов.
Croissant же ориентирован на свой специфический кейс — чтение RSS — где минимальная динамичность вполне приемлема. Важной частью экосистемы Croissant является амбициозное стремление к открытости и доступности кода, хотя на этом этапе проект еще не опубликован в открытом доступе. Автора волнуют вопросы зависимости от платформ, лицензирования и готовности продукта к публичному релизу. Обсуждается возможность использования контейнеризации, разработка Electron или Tauri приложения и даже идея коммерциализации с небольшой платой. Инфраструктура для хостинга задумывается на базе Proxmox и Tailscale, что обеспечивает гибкий доступ к сервису вне локальной сети.
Интернет-синхронизация данных, таких как подписки и состояние прочтения, пока представляется сложной задачей с учетом клиентской архитектуры. В целом Croissant — это не просто технический эксперимент, а осознанное возвращение к веб-стандартам, отказ от сложных, тяжеловесных и часто избыточных инструментов в пользу простоты, понятности и гибкости. Он демонстрирует, что современные браузеры и их возможности позволяют создавать качественные приложения, ориентированные на пользователя и его потребности, без чрезмерных слоев абстракции. Такой подход может вдохновить как отдельных разработчиков, так и команды, которые стремятся к контролю над своими проектами и минимальному техническому долгу. Croissant показывает, что no-framework приложения — это вполне реальная и жизнеспособная альтернатива, особенно для специфических и узкоспециализированных веб-продуктов, где важна надежность, производительность и контроль над каждым аспектом.
В перспективе развитие этой идеи может повлечь за собой появление новых инструментов, улучшение браузерных API и возрождение интереса к нативным веб-компонентам и реактивным паттернам без необходимости жертвовать скоростью разработки или качеством конечного продукта. Такой подход отражает уважение к истории и фундаментальным принципам веба — открытости, гибкости и доступности, сохраняя при этом инновационный дух и стремление к новым горизонтам в создании пользовательских интерфейсов.