Назад к блогу

Сколько ИИ-агентов стоит каждый килобайт JavaScript-фреймворка

Сколько ИИ-агентов стоит каждый килобайт JavaScript-фреймворка

Сравнение стоимости сборки одного и того же приложения разными ИИ-агентами на десятке JavaScript-фреймворков — от Nuxt и SvelteKit до чистого Vite — с замерами токенов, времени и денег на прогон. Автор показывает, что привычная связка «размер бандла → расход агента» не работает, и разбирает, из чего на самом деле складывается цена генерации кода.

Вопрос, который здесь разбирается, звучит провокационно: можно ли перевести килобайты JavaScript-бандла в деньги, которые агент тратит на сборку приложения на этом фреймворке. Ответ оказывается неожиданным: прямой формулы «килобайт в токены» не существует, а сама метрика стоимости устроена иначе, чем подсказывает заголовок. Разберём, что именно измерялось, как считались токены и почему размер бандла и расход агента — две отдельные величины, которые не связываются коэффициентом.

Что такое «AI cost» и в чём он измеряется

«AI cost» в этом бенчмарке — денежная стоимость одного прогона сборки приложения агентом, в долларах США. Для каждого фреймворка берётся медиана 3–5 прогонов: например, Hono+htmx — $2.67, Angular — $4.97. Рядом приводятся токены в миллионах и время в минутах, причём токены и время, по наблюдению автора, «track pretty closely with the cost» — то есть тесно следуют за стоимостью.

Цена в долларах получается не пересчётом токенов по собственной формуле автора: токены сообщает Claude Code, а цены цитируются из API Claude Code — то есть денежное значение берётся из того же отчёта, что и токены, а не вычисляется отдельно. Поэтому «AI cost» — это денежный эквивалент сборки, а не токены и тем более не килобайты.

Важная оговорка о природе цифр: цены цитируются из API Claude Code и не отражают реально потраченные деньги — автор работает на плане Max.

Как устроен эксперимент

Приложение-«holotype»

Единым сценарием служило небольшое, но нетривиальное приложение-«Покедекс» на PokéAPI: список покемонов с типами, приёмами и данными из разных игр, с поиском и фильтрацией. Автор называет его «holotype» — единственным образцом типа сайта — и прямо оговаривает границы: это преимущественно контентный сайт с малой интерактивностью, ближе к Википедии, чем к Figma или GMail. Приложение выбрано потому, что его легко понять на высоком уровне и относительно просто описать спецификацией и протестировать.

Участники и версии

В сравнении участвовали Nuxt, Qwik, React Router, SolidStart, SvelteKit, TanStack Start, Vanilla и другие, для каждого зафиксированы точные версии пакетов:

  • Nuxt — nuxt 4.6.2 и vue 3.5.44;
  • Qwik — @builder.io/qwik-city и @builder.io/qwik 1.20.2 в первой итерации и 1.20.3 в итерациях 2–5;
  • React Router — react-router 8.5.0 и react 19.3.1;
  • SolidStart — @solidjs/start 2.1.0 и solid-js 1.9.17;
  • SvelteKit — @sveltejs/kit 3.1.0 и svelte 5.57.2;
  • TanStack Start — @tanstack/react-start 1.169.4 и react 19.3.1;
  • Vanilla — vite 8.3.5.

Для Vanilla агент был проинструктирован использовать «vanilla JavaScript or TypeScript with Vite, without a UI framework». Vite выбран потому, что лежит в основе многих фреймворков и представляет достаточно стандартную и агностичную инфраструктуру JavaScript.

Агент и окружение

Спецификация передавалась модели Opus 5.5 с высоким уровнем усилий, с указанием использовать последнюю версию соответствующего фреймворка. Каждый агент работал в песочнице и не знал, что приложение будут проверять в Lighthouse на производительность и доступность, хотя получал набор тестов на соответствие. Для каждого фреймворка агент должен был использовать официальные MCP или skills этого инструмента. Прогоны повторялись, потому что результаты LLM стохастичны: «running multiple iterations did help».

Как считались медианы и интервалы

На каждый фреймворк выполнялось от 3 до 5 прогонов. Для метрик Lighthouse схема двухступенчатая: сначала медиана 5 запусков на приложение, затем медиана по 3–5 приложениям. Запись вида «3.85 M (3.16–8.18)−0.69+4.33» у Nuxt читается так: 3.85 M — медиана токенов, в скобках диапазон, а −0.69 и +4.33 — асимметричные отклонения вниз и вверх от медианы. Токены сообщал Claude Code, длительность — общее время по настенным часам.

Как агент «потребляет» фреймворк

Токены описываются как сумма чтений из кэша, некэшированного ввода и вывода, и приводятся по фреймворкам без разбивки по шагам — например, у Angular медиана 9.76 M.

Зато фиксируется, какие инструменты агент реально задействовал, и разброс здесь большой. Для SvelteKit MCP использовался во всех 5 прогонах. Для React Router skill-инструмент и skill-файлы — в 5 из 5. Для Next.js агенты читали skill-файл лишь в 1 из 5 прогонов, а AGENTS.md — в 2 из 5; это файл с инструкциями для агента, который он читает, чтобы узнать правила работы с проектом. Для TanStack Start агент находил свои skill-файлы только в 2 из 5 прогонов, причём они поставляются в node_modules проекта. Для Nuxt MCP агентами не использовался вовсе. Прямой связи между чтением skill-файлов или AGENTS.md и расходом токенов материал не устанавливает; широкий разброс автор объясняет стохастической природой LLM.

Opus 5.5, high effortофициальные инструменты фреймворкасборка Покедексанабор тестовJS, TBT, LCPcache reads, input, outputСпецификацияАгентMCP или skillsПриложениеПроверка соответствияLighthouseClaude CodeТокены

Рисунок. Из чего складывается прогон: от спецификации до замеров токенов и Lighthouse.

Как сравнивали и что получилось

Стенд: модель Opus 5.5 с высоким уровнем усилий, песочница без знания о Lighthouse, официальные MCP или skills для каждого фреймворка, от 3 до 5 прогонов на фреймворк, для Lighthouse — медиана 5 запусков на приложение с симулированным мобильным троттлингом, затем медиана по 3–5 приложениям. Повторить можно, взяв тот же «Покедекс» на PokéAPI и те же версии пакетов.

Медианные токены на прогон, отсортированные по возрастанию:

ФреймворкТокены, M
Nuxt3.85
Astro4.13
Hono+htmx4.26
Next.js4.99
Vanilla5.00
Qwik5.64
TanStack Start7.07
SolidStart7.13
React Router7.58
SvelteKit8.53
Gracile+Lit9.04
Angular9.76
Nuxt3.85 M токеновAstro4.13 M токеновHono+htmx4.26 M токеновNext.js4.99 M токеновVanilla5.00 M токеновQwik5.64 M токеновTanStack Start7.07 M токеновSolidStart7.13 M токеновReact Router7.58 M токеновSvelteKit8.53 M токеновGracile+Lit9.04 M токеновAngular9.76 M токенов

Рисунок. Медианные токены на прогон по фреймворкам, миллионы токенов.

У Angular медиана взята по 3 итерациям: дважды не удалось создать рабочее приложение.

По стоимости наибольший разброс у Angular — $4.97 (3.19–6.82)−1.78+1.85, тогда как у Hono+htmx $2.67 (2.23–3.19)−0.44+0.52. По времени тоже Angular: 17.2 min (9.8–23.7)−7.4+6.5, у Nuxt 9.0 min (8.0–17.6)−1.0+8.6. По токенам снова Angular: 9.76 M (4.92–14.94)−4.84+5.18, у Nuxt 3.85 M (3.16–8.18)−0.69+4.33. По JavaScript-байтам лидирует Angular: 93 KiB (81–102)−12+9, у Gracile+Lit 8 KiB (1–13)−7+5. По TBT наибольший разброс у Next.js: 71 ms (66–121)−5+50, у Nuxt 40 ms (14–54)−26+14. По LCP — снова Next.js: 2090 ms (1028–2187)−1062+97, у Vanilla 1667 ms (764–1676)−903+9. Итог: по большинству метрик (стоимость, время, токены, JS-байты) наибольшая вариативность у Angular, по TBT и LCP — у Next.js.

Связь с размером бандла

Токены и JavaScript-байты — две отдельные метрики бенчмарка: токены складываются из cache reads, uncached input, и output, медиана по 3–5 прогонам; JavaScript-байты отчитывает Lighthouse, медиана по 3–5 приложениям. Для Next.js, например, JS-байты составляют 142 KiB (136–143), а токены — 4.99 M (3.54–8.82), и сопоставлять их напрямую не с чем.

Что действительно утверждается: размер кода влияет на число токенов, в том числе при будущих правках, а значит — на реальную стоимость поддержки кода во времени. Дороговизна Angular объясняется общим размером кода. Сама метрика JavaScript-байтов в основном отражает размер клиентского фреймворка. А токены тесно связаны со стоимостью и временем, но не с размером бандла.

Что цифры не показывают

Автор прямо называет эксперимент несовершенным. Приложение — единственный «holotype», контентный сайт с малой интерактивностью, поэтому результаты не переносятся на сложные приложения. Архитектуру (SSR vs CSR) и уровень производительности не задавали, а фреймворки различались тем, насколько они смещены в клиент или сервер и используют ли вообще клиентский фреймворк; агент Gracile в двух прогонах даже не использовал Lit. LLM стохастичны: иногда агент уходит в сторону и тратит токены не по вине фреймворка. Lighthouse сам даёт нестабильные результаты — LCP может выбрать одно изображение «крупнейшим» элементом, а на следующем прогоне другое. В двух прогонах Angular агент построил SSR-приложение, отклонявшее не-localhost, что автор счёл нарушением спецификации и не перезапускал.

Почему сделано именно так

Автор оговаривает, что не пытается выставить какой-либо фреймворк в дурном свете, и до запуска не знал, кто победит. Результат зависит от приложения и метрик: можно было бы сделать бенчмарк в пользу SPA, выбрав сложный дашборд, видеоигру или продуктивное приложение, или мерить интерактивность внутри приложения вместо Core Web Vitals, которые жёстки к SPA. Чтобы уравнять условия, каждый фреймворк использовал официальные MCP или skills, а архитектуру и производительность не навязывали.

Для maintainability автор выбрал простой и проверенный показатель — общее число строк кода, отказавшись от навороченных метрик вроде цикломатической сложности. Смысл в том, что цель фреймворка — сократить объём кода, который нужно поддерживать, а размер кода влияет на число токенов и на реальную стоимость поддержки во времени.

Улучшить бенчмарк можно было бы, обязав агента использовать Service Workers для офлайн-кэширования, оптимизировав изображения покемонов, применив lazy-loading, fetchpriority, Speculation Rules API. Автор намеренно не направлял агентов к этим приёмам, потому что типичный вайб-кодер так не поступает. Другой вариант — предгенерировать все HTML-файлы как статические ресурсы — прямо запрещён инструкциями и проверяется тестовым стендом: это обход сути бенчмарка, цель которого — имитировать большой объём возможно динамических данных. Можно было бы прогнать больше итераций, взять других кодирующих агентов, другие уровни усилий, другие фреймворки и версии, варианты с MCP/skills и без, больше браузеров помимо Chromium, другие типы приложений — этого автор не делал в основном ради экономии времени.

Что из этого следует на практике

  • Метрика «AI cost» — это деньги за прогон сборки, а не токены и не килобайты. Планируя бюджет на агентскую разработку, ориентируйтесь на стоимость прогона, а токены и время используйте как её спутники: они идут за стоимостью тесно.
  • Размер бандла и расход агента — независимые метрики: пересчитать килобайты в токены нельзя, связь между ними утверждается только качественно — размер кода влияет на число токенов при будущих правках, то есть на стоимость поддержки.
  • Разброс внутри одного фреймворка сопоставим с разницей между фреймворками. Медианы токенов лежат в диапазоне от 3.85 M до 9.76 M, но интервалы широкие, а у Angular и Next.js особенно. Одиночный прогон не показателен — нужны итерации и медиана.
  • Использование инструментов фреймворка агентом нестабильно: MCP у Nuxt не использовался вовсе, skill-файлы Next.js читались в 1 из 5 прогонов, а TanStack Start находил свои файлы в node_modules только в 2 из 5. Если инструменты фреймворка важны для качества, рассчитывать на их автоматическое применение не приходится.
  • Результаты получены на одном контентном приложении с малой интерактивностью и без заданной архитектуры. Для сложных интерактивных приложений цифры не переносятся, а сравнение фреймворков с разным уклоном в клиент или сервер не полностью эквивалентно.

Источники

Похожее