1. Архитектура Jaspr: концептуальные отличия от Flutter Web и механизмы работы DOM
Скомпилированное веб-приложение на Flutter часто встречает пользователя пустым экраном и загрузкой нескольких мегабайт движка CanvasKit или Impeller, прежде чем отрисует первый пиксель. Для сложных интерактивных дашбордов или веб-игр это оправданная цена за pixel-perfect консистентность. Но для контентных сайтов, блогов, e-commerce и классических SaaS-платформ такой подход фатален: нулевое SEO, сложная доступность (accessibility) и избыточное потребление памяти. Jaspr появился не как конкурент Flutter, а как ответ на вопрос: что если писать на Dart, используя его строгую типизацию и компонентный подход, но рендерить результат в нативный HTML и CSS, уважая природу браузера?
Иллюзия холста против реальности узлов
Чтобы понять архитектуру Jaspr, необходимо деконструировать подход Flutter Web. Flutter переносит на веб парадигму мобильной разработки: он запрашивает у браузера пустой холст (элемент <canvas>) и берет на себя абсолютно всю работу. Маршрутизация, расчет макетов (layout), отрисовка текста, обработка скролла и жестов — все это реализуется внутри Dart-кода, скомпилированного в WebAssembly или JavaScript, который затем отдает команды низкоуровневому графическому API (WebGL/WebGPU). Браузер в этой схеме низведен до роли тупого терминала.
Jaspr кардинально меняет вектор. Он не пытается переизобрести браузерный движок рендеринга. Вместо этого Jaspr выступает в роли интеллектуального оркестратора нативного Document Object Model (DOM).
!Сравнение архитектуры рендеринга Flutter Web и Jaspr
Когда вы пишете компонент на Jaspr, вы не описываете пиксели или абстрактные геометрические примитивы. Вы описываете иерархию HTML-узлов. Это означает, что:
dart2js эффективно вырезает неиспользуемый код (tree-shaking), оставляя только логику компонентов и тонкую прослойку для работы с DOM.Анатомия DOM-ориентированного фреймворка
В основе Jaspr лежит концепция Virtual DOM (VDOM), знакомая разработчикам по экосистеме React, но адаптированная под реалии языка Dart.
Прямая манипуляция реальным DOM (вызовы вроде document.createElement или element.appendChild) — крайне ресурсоемкая операция. Реальный DOM содержит тысячи свойств для каждого узла. Если при каждом изменении состояния приложения напрямую перестраивать DOM, производительность упадет до неприемлемых значений.
Jaspr решает эту проблему через промежуточную абстракцию. Когда вызывается метод build компонента (аналог build во Flutter), Jaspr не трогает браузерный DOM. Он создает легковесное дерево Dart-объектов, представляющих желаемое состояние интерфейса.
dart
button(onClick: () => _handlePress(), [text('Нажми меня')])
``
Создается замыкание (closure) в Dart, которое передается в JavaScript как callback для addEventListener. Если компонент удаляется из дерева (unmount), Jaspr обязан корректно снять этот слушатель (removeEventListener). Если этого не сделать, возникнет утечка памяти: DOM-узел будет удерживать ссылку на Dart-функцию, не позволяя сборщику мусора Dart очистить память, выделенную под компонент. Архитектура Jaspr инкапсулирует эту логику: при уничтожении VDOM-узла фреймворк автоматически подчищает все привязанные к нему события и таймеры.
Делегирование Layout и CSS-модель
Для разработчика, пришедшего из Flutter, самым большим концептуальным сдвигом при работе с Jaspr становится отказ от виджетов компоновки. Во Flutter вы строите интерфейс, комбинируя Row, Column, Stack, Expanded и Padding. Движок Flutter проходит по этому дереву, передавая ограничения (Constraints) сверху вниз и получая размеры (Sizes) снизу вверх.
В Jaspr этих виджетов нет (хотя можно написать их эмуляторы). Архитектура Jaspr предполагает, что вы используете CSS для управления макетом.
Вместо Column вы используете div с CSS-свойством display: flex и flex-direction: column. Вместо Padding вы не оборачиваете компонент в отдельный виджет, а просто добавляете CSS-класс или инлайновый стиль padding к существующему элементу.
Это не просто синтаксическая разница, это фундаментальное различие в производительности. Браузерные движки (Blink в Chrome, Gecko в Firefox) написаны на C++ или Rust и содержат десятилетия оптимизаций для расчета Flexbox и CSS Grid. Когда Jaspr отдает браузеру HTML с классами, он перекладывает тяжелую математику расчета координат на нативный код браузера. Flutter Web же вынужден компилировать свой собственный layout-движок на Dart в Wasm/JS и выполнять эти расчеты внутри виртуальной машины, что всегда будет медленнее нативного исполнения браузером.
Компиляция и среда выполнения (dart2js и dart2wasm)
Архитектура Jaspr тесно связана с возможностями компиляторов Dart. В режиме клиентского рендеринга (SPA) код Jaspr компилируется с помощью dart2js. Этот компилятор известен своим агрессивным анализом потока управления (control flow analysis) и глобальным tree-shaking.
Поскольку Jaspr опирается на нативные HTML-теги, библиотека фреймворка очень тонкая. Компилятор видит весь граф вызовов и удаляет любые функции и классы, которые не используются в приложении. В результате минифицированный JavaScript-бандл приложения на Jaspr может весить 30-50 КБ, что сопоставимо с ванильным JS или легковесными фреймворками вроде Svelte, и недостижимо для Flutter Web, где только базовый рантайм весит больше мегабайта.
Более того, архитектура Jaspr готова к переходу на dart2wasm` — компиляцию Dart напрямую в WebAssembly. В отличие от Flutter Web, которому Wasm нужен в первую очередь для ускорения работы собственного движка рендеринга (Impeller) и тяжелых математических расчетов, Jaspr использует Wasm для ускорения бизнес-логики и алгоритма согласования VDOM. Взаимодействие с DOM из Wasm исторически было узким местом (требовались накладные расходы на вызовы через JS-прослойку), но с внедрением стандарта WasmGC (Garbage Collection в WebAssembly) и прямой интеграции с Web API, Jaspr получает возможность манипулировать DOM напрямую из Wasm-модуля с почти нулевой задержкой.
Граница применимости
Понимание архитектуры Jaspr позволяет четко определить его нишу. Jaspr не заменяет Flutter Web там, где требуется сложная нестандартная графика, манипуляция пикселями, работа с 3D или абсолютная идентичность рендеринга на мобильных устройствах и в вебе (например, Figma-подобные редакторы).
Архитектура Jaspr сияет там, где веб должен оставаться вебом. Это контентные платформы, административные панели, витрины магазинов и любые приложения, где критичны скорость первоначальной загрузки, SEO-индексация, возможность пользователя скопировать текст, работа автопереводчиков в браузере и нативная интеграция с экосистемой веб-аналитики. Jaspr берет строгую типизацию, null safety и компонентную архитектуру Dart, но вместо того, чтобы бороться с браузером, он вступает с ним в симбиоз, выступая умным контроллером для нативного DOM.