Files
transcriber/docs/adr/ADR-2026-08-11-spa-on-vue.md
T
av 54ca4c0e50 docs: фреймворком приложения выбран Vue 3 с роутером 5 и сборкой Vite
- заведены записка разведки docs/research/spa-framework.md со сравнением Svelte,
  Vue и React на одном экране и решение ADR-2026-08-11-spa-on-vue
- docs/conventions/web-ui.md переписан под Vue: компоненты, маршруты, состояние,
  обращение к API и показ ошибок
- закрыт вопрос «Приложение» в docs/architecture.md, уточнена задача spa-skeleton
2026-08-11 14:51:55 +03:00

5.8 KiB
Raw Blame History

Приложение пишем на Vue, а Node входит в гейт и в образ

Решение

Приложение пишем на Vue 3 с роутером пятой версии и собираем Vite в статику, которую бинарник вшивает через go:embed и раздаёт сам. Маршруты задаём своей таблицей через createRouter; сборочную надстройку роутера под маршруты по файлам не включаем.

Вместе с этим в проект входит шаг сборки статики: Node и npm становятся нужны на машине разработчика, отдельным шагом в task gate и слоем сборки в Dockerfile.

Это два решения, а не одно, но принимаются они вместе: шаг сборки появляется при любом из трёх кандидатов, и отдельно от выбора фреймворка его обсуждать не о чем.

Почему Vue

Разведка мерила три кандидата на одном и том же экране и нашла единственное различие, которое расходится в разы:

Различает единственное — размер того, что скачивает телефон, и он расходится вчетверо.

Вшивание в бинарник, цена шага сборки в гейте и установка на телефон у всех трёх оказались одинаковыми и потому ничего не решают.

По размеру Vue стоит посередине — 33 326 Б на четыре экрана против 17 314 у Svelte и 72 402 у React. Выбран он не по этому числу, а по устойчивости экосистемы, и оба отвергнутых кандидата отвергнуты с названной ценой:

Svelte — легче Vue вдвое, но своего роутера не имеет, а тот, что есть, держит один человек. Владелец выбрал экосистему, которая переживёт проект, а не минимальный размер: 33 КБ на телефоне не отличаются от 17 КБ на глаз, а брошенная зависимость отличается.

React — вчетверо тяжелее Svelte и вдвое тяжелее Vue, а взамен даёт экосистему, которой приложению на четыре экрана не на что потратиться.

Роутер берём пятой версии, а не четвёртой, по тому же доводу: она стабильна с 29 января 2026 и несёт метку latest, то есть чинить будут её, а не предшественницу. Её сборочная надстройка добавляет 34 пакета в установку, и это принятая цена; на собранный файл она не влияет и необязательна.

Почему это ADR

Запись проходит триггер дорогим откатом: переход на другой фреймворк переписывает все экраны разом, а не один файл. Шаг сборки сюда же — он меняет требования к машине разработчика и к образу, и снять его потом можно только вместе с приложением.

Прежнего решения запись не пересматривает: htmx был снят решением о SPA от 2026-08-10, до заведения этого журнала, и парного статуса «заменено на» ставить нечему.

Последствия

  • + разметка отделена от кода однофайловым компонентом, а роутер и хранилище состояния идут из тех же рук, что и сам фреймворк: третьей библиотеки под них заводить не нужно.
  • + собранная статика — три файла и значок, поэтому go:embed берёт каталог обычной строкой, а бинарник остаётся самодостаточным.
  • гейт перестаёт зависеть только от Go. Красный шаг сборки статики становится таким же поводом остановиться, как красный go build, а машина разработчика получает второе требуемое окружение сверх ffmpeg.
  • в образ добавляется слой Node ради шага, результат которого — три файла; насколько дольше собирается образ и насколько тяжелеет, не замерялось.
  • в проект приходит node_modules на 92 МБ и 84 пакета, за которыми надо следить отдельно от зависимостей Go: gitleaks и golangci-lint про них ничего не знают.
  • приложение весит 33 КБ там, где на Svelte весило бы 17. Разница куплена сознательно и обратно не отыгрывается.