Обзор фреймворка Jaspr (Dart)

Я не нашел на хабре достойного представления фрейморка Jaspr сообществу и решил представить сам. Flutter, безусловно, хорошая магия: один код для всех платформ, в том числе и Web. Но за магию приходится платить. Платить мегабайтами загрузки, муками с SEO и ощущением, что ты принёс на пляж боулинг — вроде и весело, но как-то не к месту. Команда Flutter и сама честно говорит: Flutter Web создан для веб-приложений, а не для веб-сайтов. Для сложных дашбордов, PWA, для всего, что живёт за логином — да. Для контентного сайта, блога, лендинга — увы.

И вот, пока мы спорим, нужен ли Dart в вебе и не проще ли взять старый добрый TypeScript, из тени вышел проект, который предлагает не воевать с вебом, а подружиться с ним.

Знакомьтесь, Jaspr. Веб-фреймворк на Dart, который осознанно отказывается от канваса и пиксельной магии Flutter в пользу старого доброго HTML и CSS. Он выглядит как Flutter, ощущается как Flutter, но на выходе даёт то, что поисковики и браузеры любят и понимают: обычный HTML-документ и DOM. А попробовать на вкус его можно здесь.

Это не «ещё один фреймворк». Это другой подход. И, возможно, именно тот, которого так не хватало экосистеме Dart, чтобы наконец-то стать полноценным фулстек-инструментом.

Философский камень: в чём фундаментальное отличие от Flutter Web?
Чтобы понять Jaspr, нужно понять его главный принцип: он не абстрагируется от веба, а принимает его. Flutter Web говорит: «Неважно, что под капотом — браузер, десктоп или холодильник. Ты пишешь на Flutter, а я сам разберусь, как это нарисовать». Он создаёт свой мир внутри тега <canvas> и полностью контролирует каждый пиксель.

Jaspr говорит иначе: «Ты в браузере. У тебя есть DOM, есть CSS, есть семантические теги. Давай использовать их». Когда вы пишете в Jaspr компонент p([text('Hello Habr')]), он не рисует пиксели, имитирующие текст. Он генерирует нативный тег <p>Hello Habr</p>.

Это простое, но кардинальное различие меняет всё:

Производительность и SEO. Вместо многомегабайтного движка для рендеринга пользователь получает лёгкий HTML. Страница отображается заметно быстрее, поиск видит осмысленный контент, а не flutter.js и пустой <body>. Для любого контентного или коммерческого сайта это важный показатель.

Экосистема. Вы можете использовать любую CSS-библиотеку. Tailwind, Bootstrap, Bulma — что угодно. Вы можете интегрировать существующие JavaScript-библиотеки. Вы работаете с вебом, а не внутри «чёрного ящика».

Привычные инструменты. Забудьте о Row и Column. Для раскладки вы используете Flexbox и Grid — стандартные, мощные и предсказуемые инструменты CSS. Это заставляет переключить мышление с «мобильного» на «вебовое», но в долгосрочной перспективе это правильный путь.

Jaspr — это не попытка запустить мобильное приложение в браузере. Это полноценный веб-фреймворк, который просто использует очень знакомый и удобный синтаксис, вдохновлённый Flutter.


Архитектура «под капотом»: SSR, SSG, гидратация и другие страшные слова
Jaspr — это не просто библиотека для рендеринга. Это современный фулстек-фреймворк, который поддерживает все актуальные режимы работы. И всё это — на чистом Dart.

SSG (Static Site Generation). Генерация статического сайта. Вы пишете код, запускаете jaspr build, и на выходе получаете пачку HTML, CSS и JS-файлов, которые можно хостить где угодно — от GitHub Pages до любого CDN. Идеально для блогов, лендингов, сайтов-документаций. Кстати, официальные сайты dart.dev и docs.flutter.dev собираются с помощью Jaspr, что немного намекает на серьёзность проекта.

SSR (Server-Side Rendering). Рендеринг на стороне сервера. Пользователь запрашивает страницу, ваш сервер на Dart генерирует HTML и немедленно отдаёт его в браузер. Пользователь видит контент сразу, а поисковики счастливы.

Client-Side Rendering (SPA). Классический одностраничник. Сервер отдаёт минимальный HTML, а дальше всё рендерится на клиенте.

Автоматическая гидратация. Это самая мякотка. В режимах SSG и SSR, после того как пользователь получил готовый HTML, Jaspr незаметно подгружает клиентский JS, «оживляет» страницу, восстанавливает состояние компонентов и навешивает обработчики событий. Статический сайт превращается в интерактивное SPA без единого скачка или перезагрузки.

Все эти подходы можно комбинировать. Например, главную страницу отрендерить статически, а личный кабинет — на клиенте. Такая гибкость даёт огромные возможности для оптимизации.


Как это выглядит в коде? Придётся ли переучиваться?
Если вы писали на Flutter, то 80% синтаксиса Jaspr вам уже знакомы.

import 'package:jaspr/jaspr.dart';

void main() {
  runApp(App());
}

class App extends StatefulComponent {
  const App({super.key});

  @override
  State<App> createState() => _AppState();
}

class _AppState extends State<App> {
  int count = 0;

  @override
  Component build(BuildContext context) {
    return div([
      text('Count is $count'),
      button(
        onClick: () {
          setState(() => count++);
        },
        [text('Press Me')],
      ),
    ]);
  }
}

Что мы здесь видим?

  • StatelessComponent и StatefulComponent — старые добрые знакомые.

  • setState() работает точно так же, как мы привыкли.

  • Декларативный подход: мы описываем состояние UI, а фреймворк сам разбирается, как его обновить в DOM.

Но есть и важные отличия, продиктованные самой природой веба:

  • Возвращаемый тип Iterable<Component>. Метод build возвращает не один виджет, а итерируемую последовательность. Это позволяет вернуть несколько компонентов на одном уровне, как это естественно для HTML (<li>Item 1</li><li>Item 2</li>). Для этого используется синтаксис sync* и ключевое слово yield.

  • HTML-теги вместо виджетов. Вместо Text, Container, Padding вы используете функции text(), div(), p(), img(), которые напрямую соответствуют HTML-тегам.

  • Стилизация через CSS. Стили — это не TextStyle или BoxDecoration. Это обычные CSS-классы или инлайн-стили, которые вы передаёте в компонент. Jaspr не навязывает вам свой способ стилизации, а даёт работать с нативными инструментами.


Dart для фулстека. Почему это имеет смысл?
Главное преимущество Jaspr — это возможность построить всё приложение, от фронтенда до бэкенда и базы данных, на одном языке. Dart для этой роли подходит идеально:

  • Строгая типизация и null-safety. После хаоса в мире JavaScript это как глоток свежего воздуха. Большая часть ошибок отлавливается на этапе компиляции.

  • Общий код. Вы можете использовать одни и те же модели данных, бизнес-логику и утилиты на клиенте и на сервере. Больше никаких проблем с синхронизацией и сериализацией.

  • Производительность. На сервере Dart компилируется в быстрый нативный код, а в разработке есть JIT-компиляция с хот-релоадом.

  • Зрелая экосистема. Большинство типичных пакетов с pub.dev (HTTP-клиенты, работа с данными, управление состоянием), не завязанных на Flutter, прекрасно работают в Jaspr-проекте.

Jaspr отлично интегрируется с серверными фреймворками на Dart, такими как Shelf, Dart Frog или Serverpod. Это позволяет строить по-настоящему монолитные (в хорошем смысле) и при этом поддерживаемые системы.


Управление состоянием: Riverpod и старые друзья
Как управлять состоянием? Так же, как вы привыкли. Поскольку Jaspr — это Dart, вы можете использовать знакомые пакеты:

  • jaspr_riverpod: специальная версия Riverpod для Jaspr, которая поддерживает SSR и синхронизацию состояния между сервером и клиентом.

  • jaspr_bloc: порт flutter_bloc для любителей BLoC-подхода.

  • Provider, GetIt и любые другие DI-контейнеры и стейт-менеджеры, не завязанные на Flutter, тоже будут работать.

    Пример RiverPod:

import 'package:jaspr/jaspr.dart';
import 'package:jaspr_riverpod/jaspr_riverpod.dart';

void main() {
  runApp(ProviderScope(child: App()));
}

final counterProvider = StateProvider((ref) => 0);

class App extends StatelessComponent {
  const App({super.key});

  @override
  Component build(BuildContext context) {
    return div([
      Builder(
        builder: (context) {
          var count = context.watch(counterProvider);
          return text('Count is $count');
        },
      ),
      button(
        onClick: () {
          context.read(counterProvider.notifier).state++;
        },
        [text('Press Me')],
      ),
    ]);
  }
}

Вам не нужно учить Redux, MobX или Zustand. Вы остаётесь в привычной и комфортной экосистеме.


Ложка дёгтя: чего не хватает?
Jaspr — молодой фреймворк, и было бы нечестно говорить, что он идеален.

  • Нет готовых UI-компонентов. Здесь нет аналогов Material или Cupertino. Кнопки, поля ввода, модальные окна — всё это придётся стилизовать с нуля или использовать сторонние CSS-фреймворки. Это не минус, а особенность, но к этому нужно быть готовым.

  • Небольшое сообщество. Пока что сообщество Jaspr невелико. Найти готовое решение на Stack Overflow будет сложнее, чем для React. Зато есть активный Discord-сервер, куда зовут прямо из официальных ресурсов Jaspr — там можно получить помощь, в том числе от автора фреймворка.

  • Экосистема в стадии становления. Ещё не для всего есть готовые «jaspr-обёртки». Иногда придётся писать немного кода для интеграции с JS-библиотеками, используя dart:js_interop.


Так кому и зачем нужен Jaspr?
Jaspr — это не «убийца React» и не замена Flutter Web. Это прагматичный инструмент для конкретных задач.

Jaspr — ваш выбор, если:

  • Вы Flutter-разработчик и вам нужен сайт: лендинг, блог, документация. Вы сделаете его на знакомом языке и сэкономите массу времени.

  • Вы хотите писать фулстек на Dart: шарить код между клиентом и сервером и иметь единую кодовую базу.

  • Вам нужен быстрый, SEO-дружелюбный сайт: новостной портал, маркетплейс, любой проект, где важна скорость первой загрузки и индексация.

  • Вы устали от JavaScript-фреймворков и хотите попробовать что-то новое, но при этом строго типизированное и предсказуемое.


Попробовать самому. Это проще, чем кажется
Начать работать с Jaspr невероятно просто.

Устанавливаем CLI:

dart pub global activate jaspr_cli

Создаём проект:

jaspr create my_awesome_site

CLI предложит пройти небольшой мастер и выбрать параметры проекта (в том числе режим рендеринга: static, server или client).

Запускаем в режиме разработки:

cd my_awesome_site
jaspr serve

Сервер поднимется с хот-релоадом, и можно начинать творить.

А для тех, кто хочет просто «пощупать» фреймворк без установки, есть онлайн-песочница JasprPad — аналог DartPad, написанный на самом Jaspr.


Заключение: тихая революция
Jaspr не кричит о себе на каждом углу. Он просто делает свою работу: даёт Dart-разработчикам возможность создавать современные, быстрые и нативные для веба сайты. Он заполняет ту самую нишу, которую не смог (и не должен был) закрыть Flutter Web.

Это эволюционный шаг для всей экосистемы Dart — шаг от «языка для мобилок» к полноценному инструменту для фулстек-разработки. И, возможно, через пару лет, когда очередной JavaScript-фреймворк объявит о своей смерти, мы просто пожмём плечами. Ведь у нас будет свой, скучный, надёжный и очень мощный инструмент на строгоми четком языке программирования. И имя ему — Jaspr.

Комментарии (14)


  1. cmyser
    06.02.2026 05:57

    это конечно всё очень здорово, но очередной тупик

    Если вы хотите реальное приложение сразу для Web / Windows / macOS / Linux / Android / iOS + WebExtension

    Которое работает и ощущается как нативное, то вам нужен $mol

    Он не создаёт вам ограничения, а даёт возможности, одинаково хорошо подходит как для статичного сайта так и для динамического приложения, и даже игр


    1. oxabadbaba
      06.02.2026 05:57

      О, молы пришли)
      1) $mol поддерживает JIT и AOT компиляцию?
      2) «Web / Windows / macOS / Linux / Android / iOS ». Можешь показать, где именно в $mol есть нативная поддержка этих платформ, кроме как через обычный WebView/Electron, как у любого веб-фреймворка?
      3) Есть список нативных фич, которые $mol даёт на десктопе/мобилке, помимо того, что даёт сам браузер?
      4) Тема статьи — Dart и Jaspr. $mol как TypeScript-фреймворк тут при чём? Он внезапно научился компилироваться из Dart или просто решил заехать в любой тред, где слово «веб» встречается?
      5) Ты серьёзно считаешь, что собственный DSL, свой формат .view.tree, свой монорепо-тулчейн и специфичный стиль кода — это «не ограничения»? Тогда как по-твоему выглядят ограничения?
      6) Про «даже для игр» особенно интересно. Можешь привести пару публичных игр на $mol с нормальной нагрузкой (а не демку на 50 строк) — чтобы увидеть, как это «подходит» на практике?
      7) интеграция с C и Rust есть?
      8) чем $mol решает именно те задачи, про которые говорит статья про Jaspr — единый язык Dart для фронта и бэка, SSR/SSG на Dart и шаринг бизнес-логики, — кроме как «забудьте про всё это и перепишите на мой любимый TS-фреймворк»?
      9) синтаксис из категории "ты себя в зеркало видел? тебе не удастся потеряться в толпе вас там не смущает?
      10) $mol в канвас умеет? 120 фпс дает? есть выбор как между jaspr и flutter из хтмл в канвас с сохранением бизнес логики?


      1. cmyser
        06.02.2026 05:57

        о, крутой комент! реально, постараюсь ответить
        1 в результате сборки получается бандл как и в других веб фреймворках, там index.html web.js web.css можно глянуть пример тут
        2 я делал через tauri тут, нативной поддержки нет, но браузер сейчас может буквально всё, тут действительно любой другой веб-фреймворк может так же
        3 да, в мол заложена невероятная гибкость, и адаптивность под все экраны из коробки, это всё еще браузер, но кода будет меньше, гораздо меньше чем у конкурентов. Я так делаю, так как считаю что "мы" незаслужено обходим вниманием лучшее решение на рынке
        4 я пришел из рекомендаций гугла, да, я слежу за всем "web" и стараюсь распространять знание о $mol. К сожалению о нем знают очень мало людей
        5 .view.tree - это dsl как раз, да, для изучения это барьер, но не сказать что большой
        если коротко - любой html элемент это класс $mol_view
        про монорепо тулчейн тут немного неккоретно, это репозиторий с компонентами просто, если разделить их на разные репозитории сборка затянется сильно, так как придется делать много git pull
        но я веду отдельными репозиториями, мол не ограничивает стиль ведения кода, хоть мульти хоть монорепо, как угодно

        на самом деле у страха глаза велики, все так боятся dsl, а ведь это просто еще один ЯП, с небольшим ( около 10 ) кол-вом ключевых знаков, и парой правил

        я помогаю с преодолением барьера, через текст понять, гораздо сложнее, я созваниваюсь и бесплатно даю консультации

        6 да, конечно, вот, в 3д https://game.hyoo.ru/
        7 нет, но в MAM можно добавить, это несложно ( но как связать его с js я сам не знаю, наверное как то можно)
        8 на $mol тоже можно писать бэк, есть улучшенный REST - HARP
        а так же гипер база, благодаря которой писать бэк вообще не нужно
        9 не понял вопроса
        10 да конечно, да, более 60 фпс думаю выдаст, какой нить треугольник серпинского без проблем рендерит тут пример не вспомню, можно в чатике @giper_dev узнать, там вроде недавно спрашивали похожий вопрос

        есть выбор как между jaspr и flutter из хтмл в канвас с сохранением бизнес логики?


        тут как напишите, не вижу проблем так реализовать, это же по сути будет класс с методом экспорта, а метод внутри не сложно поменять
        сам класс должен поддерживать свои инварианты ( поведение ) https://www.youtube.com/watch?v=ByBzzsnBnAY - тут про классы и бизнес логику, от Алексея Голобурдина, диджитализируй



        спасибо за классный список вопросов
        если где то показалось что я выражаю негативную эмоцию то уверяю - показалось!! пожалуйста давайте пообщаемся лично! если это интересно для вас


    1. lil_master Автор
      06.02.2026 05:57

      Я не знаком с $mol, но в выборе фреймворка больше руководствуюсь выбором языка, я люблю Дарт, т к тс, или особенно жс - для меня больший тупик.


  1. Skleprzzz
    06.02.2026 05:57

    Как попробовал jasp на новогодних, отлично подходит для сео одностраничников, очень легко получилось подключить scss препроцесор и даже перенести его генерацию в lib, чтобы компоненты на .dart лежали в одной папке с .scss, можно писать стили и внутри dart файла, но scss удобнее будет, а в режиме сср почти полноценная замена next


    1. oxabadbaba
      06.02.2026 05:57

      В режиме ссср)