
Последнее обновление: 28 мая 2026 г.
Quire (53 992 строки, 1620 КБ кода на Dart) создан в 2014 году на Dart и на клиенте, и на сервере. Вместо AngularDART и Polymer.dart выбраны DQuery и Bootjack ради более тонкого контроля над DOM. Ключевые решения (строгая типизация во всём стеке, общие модели данных клиента и сервера, цикл событий на сервере, tree shaking для JS) остаются актуальными и в 2026 году.
Quire — не первое веб-приложение на Dart и не последнее, но, возможно, первое, которое так сильно опирается на Dart и на клиенте, и на сервере.

Это увлекательный менеджер задач с древовидной структурой в самой основе. Сам проект насчитывает 53 992 строки, 1620 КБ кода на Dart и использует несколько открытых библиотек сообщества.
До начала работы над этим проектом мы были энтузиастами Dart и известны как команда Rikulo. Мы выпустили несколько библиотек на Dart: UI-фреймворк, UI-библиотеку, веб-сервер, сервер сообщений, клиент базы данных и другие.
Когда Dart впервые вышел в 2011 году, нас воодушевили его перспективы, и мы сразу стали использовать его в небольших частях проектов. Со временем мы решились создать полноценное приложение, написанное в основном на Dart.
Мы скромно делимся своим опытом в надежде, что он будет полезен тем, кто разрабатывает на Dart.
Причин выбрать Dart множество. Вот самые важные для нас:
У выбора Dart есть и минусы:
Благодаря строгой типизации писать на Dart гораздо надёжнее, чем на JavaScript. Кроме того, Dart менее многословен, чем Java, а иногда (например, в функциональных выражениях) даже лаконичнее чистого JavaScript. В целом работать с Dart комфортно, за исключением нескольких моментов:
Пока виртуальная машина Dart не появилась в Chrome, продукт приходится доставлять, компилируя его в JavaScript. Языков, компилируемых в JavaScript, много, но у Dart есть несколько дополнительных преимуществ.
На сервере Dart никогда не был популярной темой в сообществе, но мы считаем его сильным кандидатом на роль серверного языка, потому что:
Связанная статья: Quire получил сертификат ISO для защиты ваших данных — тот же упор на надёжность и безопасность серверной части спустя годы проявился в официальной сертификации защиты данных Quire.
В Quire около 30 импортируемых библиотек: 10 из них от сообщества, остальные выпущены командой Dart. Если вы эксперт по Dart, то, возможно, ждёте увидеть AngularDART и Polymer.dart, но на самом деле их здесь нет.
Мы не используем AngularDART, потому что:
Мы не используем и Polymer.dart, потому что:
Основа нашего клиентского стека — DQuery и Bootjack, два открытых проекта, выпущенных командой Rikulo:
Так мы построили стек приложения, чтобы использовать знания и навыки из мира JavaScript.
Stream — наш веб-сервер, написанный на чистом Dart, с маршрутизацией, фильтрами, серверным MVC и другими возможностями. Он отлично работает с моделью цикла событий. Написать обработчик запроса — значит выстроить цепочку неблокирующих процедур.
Это не только продуктивнее, но и приятнее традиционной многопоточной модели. Масштабированием сервиса и HTTPS у нас занимается nginx, а запросы он передаёт в Stream. Благодаря такой архитектуре мы запускаем и останавливаем виртуальные машины Dart по отдельности и обновляем сервер, не прерывая работу пользователей.
Работать с Dart нам нравится, и мы с нетерпением ждём новых интересных событий в его сообществе. И наконец, если вам любопытно, чего можно добиться на Dart, попробуйте наше приложение Quire. Оно бесплатное!
Читайте также: как Quire позже переосмыслили и пересоздали в версии Mark II.

Язык Dart и кодовая база Quire с момента написания статьи заметно изменились. Dart 2.0 (надёжная система типов) вышел в 2018 году, Dart 3.0 (null safety, records, patterns) — в 2023-м, а Flutter изменил ландшафт кроссплатформенного UI (мобильная команда Quire тоже перешла на него).
Но архитектурные решения, описанные выше, выдержали проверку временем лучше, чем можно ожидать.
Строгая типизация на клиенте и сервере по-прежнему окупается. Ошибки времени выполнения, которые строгая система типов ловит при сборке, остались теми же. JavaScript частично пришёл к типизации через TypeScript, но стек с типами от начала до конца встречается редко.
Класс ошибок, о котором говорил Саймон (бесчисленные мелкие ошибки), по-прежнему попадает на продакшен из нетипизированного стека.
Общие модели данных клиента и сервера по-прежнему экономят работу. Проблема дублирующихся моделей (одна на JS, другая на Python, молча расходящиеся) в 2026 году такая же, как в 2014-м. Решение (один язык от начала до конца) тоже прежнее. Команды на TypeScript и Node строят архитектуры в стиле Quire именно поэтому.
Цикл событий по-прежнему лучше многопоточности для веб-серверов. Node, Deno, Bun и собственный подход Stream в Dart сходятся в этом. Спор возобновляется каждые несколько лет и приходит к тому же выводу.
Tree shaking важен ещё больше. В 2014 году компилятор Dart с tree shaking выделял язык среди других. В 2026-м это обязательный минимум для любой сборки под JS: его умеют Webpack, Rollup, esbuild и Vite. Урок остаётся в силе, просто инструменты догнали.
Проблемы ShadowDOM из 2014 года в основном решены. Polymer.dart признали устаревшим, а Web Components повзрослели. Причины, по которым Саймон отказался от Polymer (внедрение стилей, совместная работа с фреймворками), в итоге решила сама платформа.
Общий принцип (не брать передовые фреймворки в ядро продакшен-приложения) в 2026 году применим к любому нынешнему «модному» фреймворку.
Связанная статья: Как это сделано: мобильная временная шкала на Flutter — рассказ о том, как мобильная команда Quire применила Flutter, создавая просмотр временной шкалы.
Выбор языка для приложения, которое проживёт много лет, — одно из немногих инженерных решений, которые дорого отменять. Когда команды ошибаются, повторяются четыре сценария.
1. Выбор языка с самым большим сообществом по умолчанию. У JavaScript самое большое сообщество, но «самое большое» не значит «лучше всего подходит для вашей задачи». Язык со строгой типизацией, хорошими инструментами и меньшим сообществом может превзойти разросшуюся экосистему со слабыми гарантиями.
Размер сообщества важен, но не единственный фактор.
2. Выбор стека с разными языками на клиенте и сервере. Каждая дублирующаяся модель данных — будущая ошибка. Команды, у которых Ruby на сервере и JS на клиенте, платят эту цену всегда. Команды с одним языком на обеих сторонах (Dart, TypeScript, Kotlin) избегают целого класса ошибок.
3. Ставка на передовые технологии до их стабилизации. Команда Quire в 2014 году отказалась от AngularDART и Polymer.dart, потому что у обоих оставались открытые архитектурные вопросы. AngularDART резко сменил курс, а Polymer признали устаревшим.
Правило (пусть фреймворк докажет себя в продакшене в большом масштабе, прежде чем строить на нём ядро приложения) в 2026 году тоже работает для любого «модного» фреймворка.
4. Отказ от системы типов ради краткосрочной скорости. На первой неделе нетипизированные языки кажутся быстрее. К шестому месяцу сэкономленное время с лихвой уходит на отладку. Команды, прошедшие через оба подхода в больших проектах, почти никогда не возвращаются к нетипизированному добровольно.
Ставка команды Quire на Dart в 2014 году выглядит разумной не потому, что Dart стал доминирующим (этого не случилось), а потому, что лежащие в её основе критерии (типизация, общий код клиента и сервера, цикл событий, tree shaking) за следующее десятилетие стали консенсусом в индустрии.
Хорошо выдержали время именно инженерные принципы, а не конкретные инструменты. Это верно для любого выбора языка в условиях неопределённости: выбирайте принципы, которые сможете отстоять через десять лет, а не популярность, которую можно измерить сегодня.
На Dart, и на клиенте, и на сервере. Приложение содержит около 54 000 строк кода на Dart и около 30 импортируемых библиотек.
Строгая типизация, модель наследования на классах и один язык на клиенте и сервере. Кроме того, Dart предлагал несколько современных возможностей раньше, чем их стали широко поддерживать в JavaScript.
Команде требовался более тонкий контроль над DOM, чем позволяла привязка AngularDART, а архитектурные подходы Quire не совпадали с логикой Angular. От Polymer.dart отказались, потому что ShadowDOM в то время конфликтовал с селекторами в стиле Bootstrap. Позже Polymer признали устаревшим, что подтвердило решение.
Открытые библиотеки команды Rikulo (инженерной команды Quire). DQuery — частичный порт jQuery на Dart с упором на делегирование событий. Bootjack — полный порт Bootstrap 3 с почти идентичными CSS и API.
Веб-сервер Quire, написанный на чистом Dart, по модели цикла событий. Маршрутизация, фильтры и серверный MVC встроены. Quire запускает Stream за nginx, который отвечает за масштабирование и HTTPS.