features · Sep 3, 2014

Quire: Criando um aplicativo de grande porte com Dart

✦
Traduzido por IA
· Ver em inglês

Aplicativo Quire criado com a linguagem de programação Dart

Última atualização: 28 de maio de 2026

TL;DR

O Quire (53.992 linhas, 1.620 KB de Dart) foi criado em 2014 com Dart no cliente e no servidor, usando DQuery e Bootjack em vez de AngularDART ou Polymer.dart para ter um controle mais fino do DOM. As decisões centrais (tipagem forte em toda a stack, modelos de dados compartilhados entre cliente e servidor, loop de eventos no servidor e tree shaking na saída JS) continuam válidas em 2026.

O Quire não é o primeiro aplicativo web escrito em Dart e não será o último, mas pode ser o primeiro a depender tanto do Dart, tanto no cliente quanto no servidor.

Logotipo da linguagem de programação Dart e framework do aplicativo web Quire

É um gerenciador de Tarefas divertido, com estrutura em árvore em sua essência. O projeto tem 53.992 linhas, 1.620 KB de código Dart, criado com algumas bibliotecas open source da comunidade.

Quem criou o Quire?

Antes de começar este projeto, éramos entusiastas do Dart conhecidos como a equipe Rikulo, que lançou várias bibliotecas Dart, incluindo framework de UI, biblioteca de UI, servidor web, servidor de mensagens, cliente de banco de dados etc.

Ficamos empolgados com o futuro do Dart quando ele foi lançado, em 2011, e logo começamos a usá-lo em pequenas partes de projetos. Por fim, passamos a construir um aplicativo completo feito majoritariamente em Dart. Aqui, queremos compartilhar com humildade um pouco da nossa experiência, na esperança de trazer informações úteis sobre desenvolvimento em Dart.

Por que o Quire escolheu Dart em vez de JavaScript?

Há muitos motivos para escolher o Dart. Entre eles, os mais importantes para nós são:

  • O sistema de tipos forte do Dart nos protege de incontáveis errinhos. O Dart Editor, a IDE oficial, dá feedback rápido sobre erros de tipo, além de autocompletar e facilitar o rastreamento.
  • Achamos o modelo de herança baseado em classes muito mais intuitivo que o baseado em protótipos.
  • O Dart permite usar a mesma linguagem no cliente e no servidor, compartilhando o mesmo modelo de dados e a mesma base de código.
  • O Dart corrige a maioria das armadilhas do JavaScript. Não é perfeito nisso, mas resolve 99% das velhas más surpresas.
  • O Dart já oferece hoje alguns recursos populares do JavaScript Harmony: Future (promise), Arrow Function etc.
  • O Dart tem o respaldo de uma equipe forte, com muitas bibliotecas oficiais de alta qualidade e APIs bem organizadas. Ele ainda está evoluindo, mas a especificação já é bastante estável.
  • No servidor, preferimos o modelo de loop de eventos ao multithreading.
  • O Dart faz tree shaking ao compilar para JavaScript. (Veja abaixo.)

Também há desvantagens em escolher o Dart:

  • A comunidade Dart é bem menor que a comunidade JavaScript.
  • A comunicação entre Dart e JavaScript não é trivial.
  • É mais difícil fazer polyfill de APIs em uma linguagem fortemente tipada.
  • O desempenho do Dart Editor não é o ideal para um projeto grande (ainda).

Com o apoio da tipagem forte, escrever em Dart é bem mais confiável que em JavaScript. Além disso, o Dart é menos verboso que o Java e, às vezes (por exemplo, com expressões de função), até menos verboso que o JavaScript puro. Em geral, trabalhar com Dart é confortável, exceto por algumas coisas:

  • Campos final precisam ser inicializados no inicializador, antes do corpo do construtor.
  • A especificação de mixin ainda é bastante imatura e não será corrigida antes da versão 2.0.
  • Não há parâmetro de tipo genérico para declaração de função, apenas para classes. (Claro, isso aumentaria a carga de trabalho do compilador.)

Como o Dart funciona no lado do cliente?

Antes de a Dart VM chegar ao Chrome, a expectativa era entregar o produto compilando-o para JavaScript. Há muitas linguagens que compilam para JavaScript, mas o Dart se destaca por algumas vantagens extras.

  • No desenvolvimento, rodamos o Dart nativamente no Dartium, um navegador derivado do Chromium com uma Dart VM embutida. Não precisamos compilar nessa etapa, o que nos poupa de incontáveis interrupções.
  • Nos testes e na produção, compilamos para JavaScript e rodamos em todos os principais navegadores. O compilador de Dart para JavaScript faz tree shaking, que remove do resultado o código não utilizado. Isso reduz bastante o tamanho do nosso código JavaScript.

Por que usar Dart no lado do servidor?

O Dart no servidor nunca foi um assunto badalado na comunidade Dart, mas o consideramos um forte candidato a linguagem de programação para servidor, porque:

  • Um serviço web, por sua natureza assíncrona, funciona muito bem com o modelo de loop de eventos (em vez de multithreading).
  • O código do servidor exige muito mais robustez e segurança que o do cliente. Uma linguagem fortemente tipada é muito útil nesse caso.

Related: Quire Achieves ISO Certification to Protect Your Data — a mesma ênfase em robustez e segurança no servidor aparece anos depois na certificação formal de proteção de dados do Quire.

Quais bibliotecas o Quire usa na sua stack Dart?

O Quire é construído com cerca de 30 importações de bibliotecas, das quais 10 vêm da comunidade e as demais foram lançadas pela equipe do Dart. Se você é especialista em Dart, pode imaginar que há AngularDART e Polymer.dart, mas na verdade nenhum dos dois está presente.

Não usamos o AngularDART, porque:

  • Queremos um controle refinado do DOM.
  • Usamos diretrizes de arquitetura próprias para projetar a estrutura do cliente, e esse paradigma é diferente da lógica do Angular.
  • Quando avaliamos o AngularDART, ele gerava um grande overhead no tamanho do código JavaScript compilado, mas isso melhorou muito.

Também não usamos o Polymer.dart, porque:

  • Por causa do encapsulamento e do redirecionamento de eventos, o ShadowDOM não consegue colaborar com frameworks orientados a seletores, como o Bootstrap.
  • Não é possível injetar estilo de fora do ShadowDOM. Se um conjunto de componentes de terceiros for feito com Polymer, é quase impossível para os usuários mudar seu visual. Atualização: desde dezembro de 2013, é possível modificar o estilo interno a partir de fora. Veja Shadow DOM 201.

O que são DQuery e Bootjack?

Os pilares da nossa stack no cliente são o DQuery e o Bootjack, ambos projetos open source lançados pela equipe Rikulo:

  • DQuery é um port parcial do jQuery para Dart, focado no sistema de delegação de eventos do jQuery.
  • Bootjack é um port completo do Bootstrap 3, com CSS e APIs quase idênticos.

Construímos nossa stack de aplicativo assim para aproveitar o conhecimento e as habilidades que temos do mundo JavaScript.

O que é o servidor web Stream?

O Stream é o nosso servidor web, escrito em Dart puro, com recursos de roteamento, filtros, MVC no servidor etc. Ele funciona de forma fluida com o modelo de loop de eventos. Escrever um handler de requisição é basicamente encadear uma sequência de rotinas não bloqueantes.

Além de mais produtivo, é mais agradável de usar que o modelo tradicional de multithreading. Também escalamos nosso serviço web e tratamos o HTTPS com o nginx, que delega as requisições ao Stream. Com essa arquitetura, conseguimos iniciar e encerrar VMs Dart individualmente e atualizar o servidor sem interromper a atividade dos usuários.

Conclusão

Tivemos uma experiência prazerosa trabalhando com Dart e esperamos ver mais novidades empolgantes na comunidade Dart. Por fim, se você tem curiosidade sobre o que dá para fazer com Dart, venha experimentar nosso aplicativo, o Quire. É grátis!

Read more on como o Quire foi reimaginado e reconstruído depois como Mark II.

Diagrama da arquitetura do Quire mostrando a implementação cliente-servidor em Dart

Quais lições deste projeto de 2014 ainda valem em 2026?

A linguagem Dart e a base de código do Quire evoluíram bastante desde que este post foi escrito. O Dart 2.0 (sistema de tipos sound) chegou em 2018, o Dart 3.0 (null safety, records, patterns) em 2023, e o Flutter mudou o cenário de UI multiplataforma (a própria equipe mobile do Quire migrou para ele). Mas as decisões de arquitetura descritas acima resistem melhor do que você imagina.

A tipagem forte em cliente e servidor ainda compensa. Os erros de execução que um sistema de tipos forte detecta em tempo de compilação continuam sendo os mesmos. O JavaScript avançou parte do caminho rumo à tipagem com o TypeScript, mas uma stack totalmente tipada de ponta a ponta continua rara. A classe de bugs que o Simon apontou (incontáveis errinhos) é a mesma que uma stack sem tipos leva para produção.

Modelos de dados compartilhados entre cliente e servidor ainda reduzem trabalho. O problema do modelo duplicado (um em JS, outro em Python, divergindo em silêncio) é o mesmo em 2026 que em 2014. A solução (uma única linguagem de ponta a ponta) também. Equipes de TypeScript com Node constroem arquiteturas no estilo do Quire exatamente por esse motivo.

Loop de eventos em vez de multithreading ainda vence em servidores web. Node, Deno, Bun e o próprio padrão Stream do Dart concordam nisso. O debate é reaberto a cada poucos anos e termina no mesmo lugar.

O tree shaking importa mais, não menos. Em 2014, o compilador do Dart com tree shaking era um diferencial. Em 2026, é o básico de qualquer pipeline de build voltado a JS. Webpack, Rollup, esbuild e Vite fazem isso. A lição continua valendo; as ferramentas é que alcançaram.

As preocupações de 2014 com o ShadowDOM foram em grande parte resolvidas. O Polymer.dart foi descontinuado. Os Web Components amadureceram. Os motivos que o Simon deu para evitar o Polymer (injeção de estilo, colaboração com frameworks) acabaram sendo resolvidos pela plataforma. O princípio geral (evitar frameworks de ponta no núcleo de um aplicativo em produção) ainda vale em 2026 para o framework "empolgante" da vez.

Related: How It's Made: A Flutter-Based Mobile Timeline — uma visão de como a equipe mobile do Quire usou o Flutter para criar uma vista de cronograma.

Quais são os erros mais comuns ao escolher uma linguagem para um grande aplicativo web?

Escolher a stack de linguagem de um aplicativo para vários anos é uma das poucas decisões de engenharia caras de reverter. Quatro padrões se repetem quando as equipes erram.

1. Escolher por padrão a linguagem com a maior comunidade. O JavaScript tem a maior comunidade, mas "maior" não é o mesmo que "melhor para o seu problema". Uma linguagem com sistema de tipos forte, boas ferramentas e comunidade menor pode superar um ecossistema enorme com garantias fracas. O tamanho da comunidade importa, mas não é a única coisa que importa.

2. Escolher uma stack que separa as linguagens de cliente e servidor. Todo modelo de dados duplicado é um bug esperando para acontecer. Equipes que usam Ruby no servidor e JS no cliente carregam esse custo para sempre. Equipes que compartilham uma só linguagem nos dois lados (Dart, TypeScript, Kotlin) evitam toda uma classe de bugs.

3. Adotar tecnologia de ponta antes de ela se estabilizar. A equipe do Quire evitou o AngularDART e o Polymer.dart em 2014 porque ambos tinham questões de arquitetura em aberto. O AngularDART mudou radicalmente de rumo e o Polymer foi descontinuado. A regra geral (deixe um framework se provar em produção, em escala, antes de apostar nele o núcleo do seu aplicativo) ainda vale em 2026 para o framework "empolgante" da vez.

4. Abrir mão do sistema de tipos em nome da velocidade de curto prazo. Linguagens sem tipos parecem mais rápidas na primeira semana. No sexto mês, o tempo economizado é mais do que devolvido em tempo de depuração. Equipes de engenharia que já viveram stacks sem tipos e com tipos em escala quase nunca voltam por vontade própria.

A aposta da equipe do Quire no Dart em 2014 parece razoável em retrospecto, não porque o Dart tenha se tornado dominante (não se tornou), mas porque os critérios por trás dela (tipagem, cliente e servidor compartilhados, loop de eventos, tree shaking) viraram consenso do setor na década seguinte.

As decisões que envelheceram bem foram os princípios de engenharia, não as escolhas de ferramenta. Esse padrão costuma valer para qualquer escolha de linguagem feita sob incerteza: escolha por princípios que você consiga defender daqui a uma década, não por uma popularidade que só dá para medir hoje.

Junte-se a mais de 100.000 equipes que usam o software de gerenciamento de projetos Quire — cadastre-se grátis

Perguntas frequentes

Em que linguagem o Quire é construído?

Dart, no cliente e no servidor. O aplicativo tem cerca de 54.000 linhas de código Dart, com cerca de 30 importações de bibliotecas.

Por que o Quire escolheu Dart em vez de JavaScript ou TypeScript?

Tipagem forte, modelo de herança baseado em classes e uma única linguagem no cliente e no servidor. O Dart também oferecia alguns recursos modernos antes de o JavaScript tê-los amplamente.

Por que o Quire não usou AngularDART ou Polymer.dart?

A equipe queria um controle do DOM mais refinado do que o binding do AngularDART permitia, e os padrões de arquitetura do Quire não combinavam com a lógica do Angular. O Polymer.dart foi evitado porque, na época, o ShadowDOM entrava em conflito com seletores no estilo Bootstrap. O Polymer foi depois descontinuado, o que validou a decisão.

O que são DQuery e Bootjack?

Bibliotecas open source da equipe Rikulo (a equipe de engenharia do Quire). O DQuery é um port parcial do jQuery para Dart, focado em delegação de eventos. O Bootjack é um port completo do Bootstrap 3, com CSS e APIs quase idênticos.

O que é o Stream na stack do Quire?

O servidor web do Quire, escrito em Dart puro, usando o modelo de loop de eventos. Roteamento, filtros e MVC no servidor já vêm incluídos. O Quire executa o Stream por trás do nginx, que cuida da escala e do HTTPS.

Simon Pai
Co-Founder at Bookshow