Topcoat: новый full-stack фреймворк для Rust без сборки WebAssembly

Разработчики представили Topcoat, модульный, «всё включено» full-stack фреймворк для Rust. Проект прямо называет себя ранней и экспериментальной разработкой: авторы предупреждают, что стоит ожидать обратно несовместимых изменений.
Главная идея фреймворка, убрать разделение на бэкенд и отдельный клиентский слой. Компоненты в Topcoat асинхронные и могут напрямую обращаться к базе данных прямо в разметке, что избавляет от привычной прослойки в виде отдельного API-слоя между сервером и интерфейсом. Вся разметка по умолчанию рендерится на сервере через макрос view!, который сохраняет синтаксис, близкий к обычным HTML и Rust: внутри шаблонов можно использовать привычные конструкции языка, циклы for, условия if, прямо в разметке.
Для интерактивности без обращения к серверу используются выражения вида $(...), это обычный типизированный код на Rust, который Topcoat выполняет на сервере при первом рендере и одновременно транслирует в JavaScript, чтобы то же выражение мгновенно повторно выполнялось уже в браузере. При этом не требуется сборка в WebAssembly и отдельный клиентский билд-процесс, в этом ключевое отличие подхода Topcoat от других full-stack фреймворков Rust, которые обычно компилируют клиентскую часть в WASM.
Когда обновление интерфейса всё же требует обращения к серверу (например, свежие результаты поиска), компонент помечается атрибутом #[shard]: Topcoat перерисовывает такой компонент на сервере при каждом изменении переданных ему сигнальных аргументов и подменяет получившийся HTML на странице, без полной перезагрузки.
Фреймворк умеет опционально выводить дерево маршрутов прямо из структуры модулей проекта без отдельного шага сборки: например, файл src/app/about.rs автоматически становится маршрутом /about, а src/app/api/health.rs, обработчиком GET /api/health. Также есть отдельная CLI-команда topcoat fmt для автоматического форматирования кода внутри макросов view! и других макросов фреймворка по всей кодовой базе.
В комплекте идёт система работы с ассетами: специальный бандлер сканирует скомпилированный бинарник на предмет вызовов asset!, копирует (или при необходимости скачивает) нужные файлы в локальную директорию и раздаёт их с эффективным кешированием в браузере по хеш-адресам. Фреймворк также включает утилиты для веб-шрифтов и иконок с готовыми интеграциями Fontsource (шрифты Google Fonts) и Iconify, а также опциональную фичу для интеграции Tailwind CSS.
Репозиторий проекта размещён на GitHub по адресу tokio-rs/topcoat. На Hacker News публикация набрала 83 очка и 40 комментариев за первые часы после выхода.
Ключевые факты
- Topcoat, экспериментальный full-stack фреймворк для Rust; разработчики прямо предупреждают об ожидаемых обратно несовместимых изменениях
- Вся разметка рендерится на сервере, компоненты асинхронны и могут напрямую обращаться к базе данных без отдельного API-слоя
- Выражения $(...), обычный типизированный Rust-код, который выполняется и на сервере при первом рендере, и транслируется в JavaScript для мгновенной работы в браузере, без сборки WebAssembly и клиентского билда
- Компоненты с атрибутом #[shard] перерисовываются на сервере при изменении их аргументов и подменяют HTML на странице без перезагрузки
- Фреймворк умеет выводить маршруты из структуры файлов проекта и включает систему ассетов с кешированием, шрифтами, иконками и опциональной интеграцией Tailwind
Почему это важно
Большинство full-stack фреймворков для Rust (например, из экосистемы Leptos или Yew) собирают клиентскую часть в WebAssembly, это отдельный шаг сборки и отдельный рантайм в браузере. Topcoat пробует другой путь: один и тот же код на Rust внутри выражений $(...) выполняется на сервере при первом рендере и одновременно транслируется в обычный JavaScript, который затем сам работает в браузере без WASM-бандла. Это заметно упрощает модель разработки full-stack приложений на Rust и объясняет живой интерес на Hacker News, 83 очка и 40 комментариев за первые часы.
Кому это важно
В первую очередь Rust-разработчикам, которые хотят писать серверный и клиентский код в одном языке и одном проекте, не поднимая отдельный JS-фронтенд и не настраивая сборку в WebAssembly. Также интересно тем, кто следит за развитием подходов к full-stack разработке в экосистеме Rust и ищет альтернативы более тяжеловесным WASM-фреймворкам.
Как это применить
Проект предлагает CLI для создания нового проекта и запуска дев-сервера, макрос #[page] для описания страниц и макрос view! для разметки в HTML-подобном синтаксисе с обычными конструкциями Rust (циклы, условия). Маршруты можно выводить автоматически из структуры файлов проекта (например, app/about.rs становится маршрутом /about) либо описывать вручную. Для компонентов, которым нужно обновление с сервера, используется атрибут #[shard]. Форматирование кода внутри макросов делает отдельная команда topcoat fmt. Ассеты объявляются вызовом asset! и раздаются с кешированием; есть готовые интеграции шрифтов (Fontsource/Google Fonts), иконок (Iconify) и опциональная поддержка Tailwind CSS.
Можно ли доверять
Сам проект честно обозначен авторами как ранняя, экспериментальная разработка с ожидаемыми обратно несовместимыми изменениями, то есть не готов для продакшена. Репозиторий размещён на GitHub по адресу tokio-rs/topcoat, публикация вызвала заметный отклик на Hacker News (83 очка, 40 комментариев), что говорит о реальном интересе сообщества, но не о зрелости самого фреймворка.
Риски и подводные камни
Статус «подчёркнуто экспериментальный» означает, что API фреймворка может меняться без сохранения обратной совместимости, рискованно закладывать Topcoat в долгоживущие проекты уже сейчас. Подход без сборки в WebAssembly менее обкатан, чем устоявшиеся решения вроде Leptos или Dioxus, а значит меньше готовых примеров, плагинов и опыта сообщества. Дуальная модель выполнения кода (одно и то же выражение работает и на сервере, и транслируется в JS), не самый распространённый паттерн, и его отладка может отличаться от привычной для Rust-разработчиков.
«Ранняя стадия разработки, экспериментальный статус. Ожидайте обратно несовместимых изменений.»
— документация Topcoat