features · Sep 3, 2014

Quire: cómo crear una aplicación grande con Dart

✦
Traducido por IA
· Ver en inglés

Aplicación Quire creada con el lenguaje de programación Dart

Última actualización: 28 de mayo de 2026

TL;DR

Quire (53 992 líneas, 1620 KB de Dart) se creó en 2014 con Dart tanto en el cliente como en el servidor, y usó DQuery y Bootjack en lugar de AngularDART o Polymer.dart para controlar mejor el DOM. Las decisiones clave (tipado fuerte en todo el stack, modelos de datos compartidos entre cliente y servidor, bucle de eventos en el servidor y tree shaking para generar JS) siguen vigentes en 2026.

Quire no es la primera aplicación web escrita en Dart ni será la última, pero podría ser la primera que depende tanto de Dart, tanto en el cliente como en el servidor.

Logotipo del lenguaje de programación Dart y framework de la aplicación web Quire

Es un divertido gestor de tareas con estructura de árbol en su esencia. El proyecto tiene 53992 líneas y 1620 KB de código Dart, y está construido con algunas bibliotecas de código abierto de la comunidad.

¿Quién creó Quire?

Antes de empezar este proyecto, éramos entusiastas de Dart conocidos como el equipo de Rikulo, y habíamos publicado varias bibliotecas de Dart, entre ellas un framework de interfaz, una biblioteca de interfaz, un servidor web, un servidor de mensajería y un cliente de base de datos.

Cuando Dart se lanzó en 2011, nos entusiasmó el valor de su futuro y enseguida empezamos a usarlo en pequeñas partes de proyectos. Con el tiempo pasamos a crear una aplicación completa hecha en su mayor parte con Dart. Aquí queremos compartir con humildad parte de nuestra experiencia, con la esperanza de aportarte información sobre cómo es desarrollar en Dart.

¿Por qué eligió Quire Dart en lugar de JavaScript?

Hay muchísimas razones para elegir Dart. Las más importantes para nosotros son:

  • El sistema de tipos fuerte de Dart nos protege de incontables errores pequeños. Dart Editor, el IDE oficial, da respuesta rápida sobre errores de tipos, ofrece autocompletado y facilita el rastreo.
  • Creemos que el modelo de herencia basado en clases es mucho más intuitivo que el basado en prototipos.
  • Dart permite usar el mismo lenguaje en el cliente y en el servidor, y compartir el mismo modelo de datos y la misma base de código.
  • Dart corrige la mayoría de las trampas de JavaScript. No es perfecto en esto, pero resuelve el 99 % de las viejas malas sorpresas.
  • Dart ya ofrece algunas funciones populares de JavaScript Harmony: Future (promesas), funciones flecha, etc.
  • Dart cuenta con el respaldo de un equipo sólido, con muchas bibliotecas oficiales de alta calidad y API bien organizadas. Dart sigue evolucionando, pero la especificación ya es bastante estable.
  • En el servidor, preferimos el modelo de bucle de eventos al multihilo.
  • Dart aplica tree shaking al compilar a JavaScript. (Más abajo lo explicamos.)

Elegir Dart también tiene contras:

  • La comunidad de Dart es mucho más pequeña que la de JavaScript.
  • La comunicación entre Dart y JavaScript no es trivial.
  • Es más difícil hacer polyfill de API en un lenguaje de tipado fuerte.
  • El rendimiento de Dart Editor no es óptimo (todavía) para proyectos grandes.

Gracias al soporte de tipado fuerte, escribir en Dart es mucho más fiable que hacerlo en JavaScript. Además, Dart es menos verboso que Java y, a veces (por ejemplo, con las expresiones de función), incluso menos que JavaScript puro. En general, trabajar con Dart es cómodo, salvo por algunas cosas:

  • Los campos final deben inicializarse en el inicializador, antes del cuerpo del constructor.
  • La especificación de mixins es bastante inmadura y no se corregirá antes de la versión 2.0.
  • No hay parámetros de tipo genérico para declaraciones de funciones, solo para clases. (Por supuesto, esto aumentaría la carga de trabajo del compilador.)

¿Cómo funciona Dart en el cliente?

Hasta que la máquina virtual de Dart llegue a Chrome, lo normal es entregar el producto compilándolo a JavaScript. Hay muchísimos lenguajes que compilan a JavaScript, pero Dart destaca por algunas ventajas adicionales.

  • En desarrollo, ejecutamos Dart de forma nativa en Dartium, un navegador derivado de Chromium con una máquina virtual de Dart integrada. En esta fase no necesitamos compilar, y nos ahorramos incontables interrupciones.
  • En pruebas y producción, lo compilamos a JavaScript y lo ejecutamos en todos los navegadores principales. El compilador de Dart a JavaScript aplica tree shaking, que elimina del resultado el código sin usar. Esto reduce mucho el tamaño de nuestro código JavaScript.

¿Por qué usar Dart en el servidor?

Dart en el servidor nunca fue un tema candente en la comunidad de Dart, pero lo consideramos un candidato sólido como lenguaje de servidor, porque:

  • Un servicio web, por su naturaleza asíncrona, funciona muy bien con el modelo de bucle de eventos (frente al multihilo).
  • El código del servidor exige mucha más robustez y seguridad que el del cliente. Un lenguaje de tipado fuerte resulta muy útil en este sentido.

Relacionado: Quire obtiene la certificación ISO para proteger tus datos — el mismo énfasis en la robustez y la seguridad del servidor aparece años después en la certificación formal de protección de datos de Quire.

¿Qué bibliotecas usa Quire en su stack de Dart?

Quire se construye con alrededor de 30 importaciones de bibliotecas, de las cuales 10 vienen de la comunidad y el resto las publica el equipo de Dart. Si eres experto en Dart, quizá supongas que están AngularDART y Polymer.dart, pero en realidad ninguno de los dos está presente.

No usamos AngularDART, porque:

  • Queremos un control fino del DOM.
  • Usamos pautas de arquitectura propias para diseñar la estructura del cliente, y su paradigma es distinto de la lógica de Angular.
  • Cuando evaluamos AngularDART, generaba una gran sobrecarga en el tamaño del código JavaScript compilado, aunque esto ha mejorado mucho.

Tampoco usamos Polymer.dart, porque:

  • Debido a la encapsulación y a la redirección de eventos, ShadowDOM no puede colaborar con frameworks orientados a selectores, como Bootstrap.
  • No se puede inyectar estilo desde fuera de ShadowDOM. Si un conjunto de componentes de terceros está hecho con Polymer, a los usuarios les resulta casi imposible cambiar su aspecto. Actualización: desde diciembre de 2013 se puede modificar el estilo interno desde fuera. Consulta Shadow DOM 201.

¿Qué son DQuery y Bootjack?

Las piedras angulares de nuestro stack de cliente son DQuery y Bootjack, dos proyectos de código abierto publicados por el equipo de Rikulo:

  • DQuery es un port parcial de jQuery a Dart, centrado en el sistema de delegación de eventos de jQuery.
  • Bootjack es un port completo de Bootstrap 3, con CSS y API casi idénticos.

Construimos nuestro stack de aplicación de este modo para aprovechar nuestros conocimientos y habilidades del mundo JavaScript.

¿Qué es el servidor web Stream?

Stream es nuestro servidor web, escrito en Dart puro y equipado con enrutamiento, filtros, MVC del lado del servidor, etc. Stream funciona sin fricciones con el modelo de bucle de eventos. Escribir un controlador de solicitudes consiste simplemente en encadenar una secuencia de rutinas no bloqueantes.

Es más productivo y también más agradable que el modelo tradicional de multihilo. Además, escalamos nuestro servicio web y gestionamos HTTPS con nginx, y delegamos las solicitudes en Stream. Con esta arquitectura podemos iniciar y detener máquinas virtuales de Dart de forma individual y actualizar el servidor sin interrumpir la actividad de los usuarios.

Conclusión

Trabajar con Dart ha sido una experiencia agradable, y esperamos con ilusión nuevos avances en la comunidad de Dart. Por último, si tienes curiosidad por lo que puedes lograr con Dart, ven a probar nuestra aplicación, Quire. ¡Es gratis!

Más información sobre cómo se reimaginó y se reconstruyó Quire como Mark II.

Diagrama de arquitectura de Quire que muestra la implementación cliente-servidor con Dart

¿Qué lecciones de esta creación de 2014 siguen vigentes en 2026?

Tanto el lenguaje Dart como el código de Quire han evolucionado mucho desde que se escribió este artículo. Dart 2.0 (sistema de tipos sólido) llegó en 2018, Dart 3.0 (null safety, records, patrones) en 2023, y Flutter cambió el panorama de la interfaz multiplataforma (el propio equipo móvil de Quire se pasó a él). Pero las decisiones de arquitectura que se documentan arriba resisten mejor de lo que cabría esperar.

El tipado fuerte en cliente y servidor sigue compensando. Los errores de ejecución que un sistema de tipos fuerte detecta en compilación siguen siendo los mismos. JavaScript avanzó en parte hacia el tipado con TypeScript, pero un stack totalmente tipado de punta a punta sigue siendo raro. La clase de errores que mencionó Simon (incontables errores pequeños) es la misma que un stack sin tipos lleva a producción.

Compartir modelos de datos entre cliente y servidor sigue ahorrando trabajo. El problema del modelo duplicado (uno en JS, otro en Python, desajustándose en silencio) es el mismo en 2026 que en 2014. La solución (un solo lenguaje de punta a punta) también. Los equipos de TypeScript sobre Node construyen arquitecturas al estilo de Quire por esta misma razón.

El bucle de eventos sigue ganando al multihilo en los servidores web. Node, Deno, Bun y el propio patrón Stream de Dart coinciden en esto. El argumento se ha vuelto a discutir cada pocos años y siempre llega a la misma conclusión.

El tree shaking importa más, no menos. En 2014, el compilador de Dart con tree shaking era un factor diferenciador. En 2026, es lo mínimo exigible a cualquier pipeline de compilación que genere JS. Webpack, Rollup, esbuild y Vite lo hacen. La lección sigue en pie; las herramientas se pusieron al día.

Las preocupaciones de 2014 sobre ShadowDOM quedaron en su mayoría resueltas. Polymer.dart quedó obsoleto. Los Web Components maduraron. Las razones que dio Simon para evitar Polymer (inyección de estilos, colaboración con frameworks) acabaron resolviéndose en la propia plataforma. El principio general (evitar los frameworks de vanguardia para el núcleo de una aplicación en producción) sigue vigente en 2026 para el framework «emocionante» del momento.

Relacionado: Así se hizo: una cronología móvil basada en Flutter — un vistazo a cómo el equipo móvil de Quire usó Flutter para crear una vista de cronología.

¿Cuáles son los errores más comunes al elegir un lenguaje para una aplicación web grande?

Elegir el stack de lenguajes de una aplicación a varios años es una de las pocas decisiones de ingeniería que resultan caras de revertir. Cuando los equipos se equivocan, se repiten cuatro patrones.

1. Elegir por defecto el lenguaje con la comunidad más grande. JavaScript tiene la comunidad más grande, pero «la más grande» no equivale a «la que mejor encaja con tu problema». Un lenguaje con un sistema de tipos fuerte, buenas herramientas y una comunidad más pequeña puede superar a un ecosistema enorme con garantías débiles. El tamaño de la comunidad importa, pero no es lo único que importa.

2. Elegir un stack que separa los lenguajes de cliente y servidor. Cada modelo de datos duplicado es un error en potencia. Los equipos que usan Ruby en el servidor y JS en el cliente arrastran ese coste para siempre. Los que comparten un único lenguaje en ambas capas (Dart, TypeScript, Kotlin) evitan toda una categoría de errores.

3. Adoptar lo más novedoso antes de que se estabilice. El equipo de Quire evitó AngularDART y Polymer.dart en 2014 porque ambos tenían cuestiones de arquitectura abiertas. AngularDART dio un giro brusco y Polymer quedó obsoleto. La regla general (deja que un framework se demuestre en producción a gran escala antes de apostar por él el núcleo de tu aplicación) sigue vigente en 2026 para el framework «emocionante» del momento.

4. Prescindir del sistema de tipos por velocidad a corto plazo. Los lenguajes sin tipos parecen más rápidos en la primera semana. Al sexto mes, el tiempo ahorrado se paga con creces en depuración. Los equipos de ingeniería que han vivido a escala tanto stacks sin tipos como con tipos casi nunca vuelven atrás por voluntad propia.

La apuesta de 2014 del equipo de Quire por Dart parece razonable en retrospectiva, no porque Dart se haya vuelto dominante (no lo hizo), sino porque los criterios de fondo (tipado, cliente y servidor compartidos, bucle de eventos, tree shaking) se convirtieron en consenso de la industria durante la década siguiente.

Lo que envejeció bien fueron los principios de ingeniería de fondo, no las herramientas concretas. Ese patrón suele cumplirse en cualquier elección de lenguaje hecha con incertidumbre: elige por principios que puedas defender dentro de una década, no por una popularidad que puedes medir hoy.

Únete a más de 100 000 equipos que usan el software de gestión de proyectos Quire: regístrate gratis

Preguntas frecuentes

¿En qué lenguaje está creado Quire?

Dart, tanto en el cliente como en el servidor. La aplicación tiene alrededor de 54 000 líneas de código Dart, con unas 30 importaciones de bibliotecas.

¿Por qué eligió Quire Dart en lugar de JavaScript o TypeScript?

Tipado fuerte, un modelo de herencia basado en clases y un solo lenguaje en cliente y servidor. Dart también ofrecía algunas funciones modernas antes de que JavaScript las admitiera de forma generalizada.

¿Por qué no usó Quire AngularDART ni Polymer.dart?

El equipo quería un control del DOM más fino que el que permitía el enlace de AngularDART, y los patrones de arquitectura de Quire no encajaban con la lógica de Angular. Se evitó Polymer.dart porque, en aquel momento, ShadowDOM chocaba con los selectores al estilo de Bootstrap. Más tarde Polymer quedó obsoleto, lo que validó la decisión.

¿Qué son DQuery y Bootjack?

Bibliotecas de código abierto del equipo de Rikulo (el equipo de ingeniería de Quire). DQuery es un port parcial de jQuery a Dart centrado en la delegación de eventos. Bootjack es un port completo de Bootstrap 3 con CSS y API casi idénticos.

¿Qué es Stream en el stack de Quire?

El servidor web de Quire, escrito en Dart puro y basado en el modelo de bucle de eventos. Incluye enrutamiento, filtros y MVC del lado del servidor. Quire ejecuta Stream detrás de nginx, que se encarga del escalado y de HTTPS.

Simon Pai
Co-Founder at Bookshow