Comparación de frameworks
Si estás leyendo esta página, probablemente hayas usado otros frameworks para construir aplicaciones y quieres saber si Mithril.js te ayudaría a resolver tus problemas de manera más efectiva.
¿Por qué no [insertar framework favorito aquí]?
La realidad es que la mayoría de los frameworks modernos son rápidos y adecuados para construir aplicaciones complejas y mantenibles si sabes cómo usarlos de manera efectiva. Hay ejemplos de aplicaciones altamente complejas en el mundo real que utilizan casi todos los frameworks populares: Udemy usa Angular, AirBnB usa React, GitLab usa Vue, Guild Wars 2 usa Mithril.js (¡sí, dentro del juego!). Claramente, todos estos son frameworks de calidad para producción.
Generalmente, si tu equipo ya tiene experiencia con otro framework/librería/tecnología, es mejor continuar usándolo, a menos que exista una razón de peso para justificar una reescritura costosa.
Sin embargo, si estás comenzando algo nuevo, considera darle una oportunidad a Mithril.js, aunque solo sea para ver el valor que los usuarios de Mithril.js han obtenido con menos de 10kb (comprimido con gzip) de código. Mithril.js es utilizado por muchas empresas conocidas (por ejemplo, Vimeo, Nike, Fitbit) y también impulsa grandes plataformas de código abierto (por ejemplo, Lichess, Flarum).
¿Por qué usar Mithril.js?
En resumen: porque Mithril.js es pragmático. Esta guía de 10 minutos es un buen ejemplo: eso es lo que se tarda en aprender componentes, XHR y enrutamiento, y esa es la cantidad justa de conocimiento necesario para construir aplicaciones útiles.
Mithril.js se enfoca en hacer un trabajo significativo de manera eficiente. ¿Hacer cargas de archivos? La documentación te muestra cómo. ¿Autenticación? También está documentado. ¿Animaciones de salida? Lo tienes. Sin librerías adicionales, sin magia.
Comparaciones
React
React es una librería de vistas mantenida por Facebook.
React y Mithril.js comparten muchas similitudes. Si ya has aprendido React, ya sabes casi todo lo que necesitas para construir aplicaciones con Mithril.
- Ambos usan DOM virtual, métodos de ciclo de vida y reconciliación basada en key.
- Ambos organizan las vistas a través de componentes.
- Ambos usan JavaScript como mecanismo de control de flujo dentro de las vistas.
La diferencia más obvia entre React y Mithril.js está en su alcance. React es una librería de vistas, por lo que una aplicación típica basada en React depende de librerías de terceros para el enrutamiento, XHR y la gestión del estado. El uso de un enfoque orientado a la librería permite a los desarrolladores personalizar su stack para que coincida precisamente con sus necesidades. Una forma menos amable de decirlo es que las arquitecturas basadas en React pueden variar enormemente de un proyecto a otro, y que es mucho más probable que esos proyectos superen la línea de 1MB de tamaño.
Mithril.js tiene módulos incorporados para necesidades comunes como el enrutamiento y XHR, y la guía muestra el uso adecuado. Este enfoque es preferible para los equipos que valoran la consistencia y la facilidad de incorporación.
Rendimiento
Tanto React como Mithril.js se preocupan mucho por el rendimiento de la renderización, pero lo hacen de diferentes maneras. En el pasado, React tenía dos implementaciones de renderización del DOM (una usando la API del DOM y otra usando innerHTML
). Su próxima arquitectura de fibra introduce la programación y la priorización de las unidades de trabajo. React también tiene un sistema de compilación sofisticado que desactiva varias comprobaciones y mensajes de error para las implementaciones de producción, y varias optimizaciones específicas del navegador. Además, también hay varias librerías orientadas al rendimiento que aprovechan el hook shouldComponentUpdate
de React y las propiedades de comprobación rápida de la igualdad de objetos de las librerías de estructuras de datos inmutables para reducir los tiempos de reconciliación del DOM virtual. En general, el enfoque de React para el rendimiento es diseñar soluciones relativamente complejas.
Mithril.js sigue la escuela de pensamiento de menos es más. Tiene una base de código sustancialmente más pequeña y agresivamente optimizada. La razón es que una base de código pequeña es más fácil de revisar y optimizar, lo que resulta en una mayor eficiencia.
Aquí hay una comparación de los tiempos de carga de la librería, es decir, el tiempo que se tarda en analizar y ejecutar el código JavaScript para cada framework, añadiendo una llamada console.time()
en la primera línea y una llamada console.timeEnd()
en la última de un script que se compone únicamente de código de framework. Para facilitar la lectura, se presentan los mejores resultados de 20 pruebas, donde se añadió manualmente código de registro a los scripts empaquetados. Las pruebas se realizaron en Chrome, desde el sistema de archivos, en un PC de escritorio de 2010.
React | Mithril.js |
---|---|
55.8 ms | 4.5 ms |
Los tiempos de carga de la librería son importantes en las aplicaciones que no permanecen abiertas durante largos periodos de tiempo (por ejemplo, cualquier cosa en el móvil) y no pueden mejorarse mediante el almacenamiento en caché u otras técnicas de optimización.
Dado que se trata de un micro-benchmark, te animamos a replicar estas pruebas, ya que el hardware puede afectar significativamente los resultados. Ten en cuenta que frameworks de empaquetado como Webpack pueden reorganizar las dependencias antes de las llamadas del temporizador, simulando así la resolución estática de módulos, por lo que debes copiar el código de los archivos CDN compilados o abrir el archivo de salida de la librería de empaquetado, y añadir manualmente las llamadas del temporizador de alta resolución console.time
y console.timeEnd
al script empaquetado. Evita el uso de new Date
y performance.now
, ya que esos mecanismos no son tan estadísticamente precisos.
Para su comodidad de lectura, aquí hay una versión de ese benchmark adaptada para usar CDNs en la web: la prueba comparativa para React está aquí, y la prueba comparativa para Mithril.js está aquí. Ten en cuenta que estamos comparando todo Mithril.js en lugar de comparar solo el módulo de renderización (que sería equivalente en alcance a React). También ten en cuenta que esta configuración basada en CDN incurre en algunos gastos generales debido a la obtención de recursos de la caché de disco (~2ms por recurso). Debido a estas razones, los números aquí no son completamente precisos, pero deberían ser suficientes para observar que la velocidad de inicialización de Mithril.js es notablemente mejor que la de React.
Aquí hay una prueba comparativa ligeramente más significativa: medir el tiempo de scripting para crear 10,000 divs (y 10,000 nodos de texto). De nuevo, aquí está el código de la prueba comparativa para React y Mithril.js. Sus mejores resultados se muestran a continuación:
React | Mithril.js |
---|---|
99.7 ms | 42.8 ms |
Lo que muestran estos números es que no solo Mithril.js se inicializa significativamente más rápido, sino que puede procesar más de 20,000 nodos del DOM virtual antes de que React esté listo para usar.
Rendimiento de actualización
El rendimiento de la actualización puede ser incluso más importante que el rendimiento de la primera renderización, ya que las actualizaciones pueden ocurrir muchas veces mientras se ejecuta una Single Page Application.
Una herramienta útil para comparar el rendimiento de la actualización es una herramienta desarrollada por el equipo de Ember llamada DbMonster. Actualiza una tabla tan rápido como puede y mide los fotogramas por segundo (FPS) y los tiempos de JavaScript (mínimo, máximo y medio). El recuento de FPS puede ser difícil de evaluar, ya que también incluye los tiempos de repintado del navegador y la latencia introducida por setTimeout
, por lo que el tiempo medio de renderización es el dato más relevante. Puedes comparar una implementación de React y una implementación de Mithril.js. Los resultados de la muestra se muestran a continuación:
React | Mithril.js |
---|---|
12.1 ms | 6.4 ms |
Rendimiento del desarrollo
Otra cosa a tener en cuenta es que, debido a que React añade comprobaciones adicionales y mensajes de error útiles en el modo de desarrollo, es más lento en el desarrollo que la versión de producción utilizada para las pruebas comparativas anteriores. Para ilustrar, aquí está la prueba comparativa de 10,000 nodos de arriba usando la versión de desarrollo de React.
Reemplazos directos
Hay varios proyectos que afirman paridad de API con React (algunos a través de librerías de capa de compatibilidad), pero no son totalmente compatibles (por ejemplo, el soporte de PropType suele ser truncado, los eventos sintéticos a veces no son compatibles y algunas APIs tienen diferentes semánticas). Ten en cuenta que estas librerías normalmente también incluyen funcionalidades adicionales propias que no forman parte de la API oficial de React, lo que puede ser problemático en el futuro si uno decide volver a React Fiber.
Las afirmaciones sobre el pequeño tamaño de descarga (en comparación con React) son precisas, pero la mayoría de estas librerías son ligeramente más grandes que el módulo de renderización de Mithril.js. Preact es la única excepción.
Ten cuidado con las afirmaciones agresivas sobre el rendimiento, ya que se sabe que las pruebas comparativas utilizadas por algunos de estos proyectos están desactualizadas y son defectuosas (en el sentido de que pueden ser -y son- explotadas). Boris Kaul (autor de algunas de las pruebas comparativas) ha escrito en detalle sobre cómo se manipulan las pruebas comparativas. Otra cosa a tener en cuenta es que algunas pruebas comparativas utilizan agresivamente características de optimización avanzadas y, por lo tanto, demuestran el rendimiento potencial, es decir, el rendimiento que es posible dadas algunas advertencias, pero que es realista que sea poco probable a menos que dediques activamente tiempo a revisar toda su base de código identificando candidatos de optimización y evaluando los riesgos de regresión que traen las advertencias de optimización.
Con el espíritu de demostrar las características de rendimiento típicas, las pruebas comparativas presentadas en esta página de comparación se implementan de una manera ingenua e idiomática de manzanas con manzanas (es decir, la forma en que normalmente escribirías el 99% de tu código) y no emplean trucos u optimizaciones avanzadas para hacer que uno u otro framework parezca artificialmente mejor. Se te invita a contribuir con una Pull Request si crees que alguna implementación de DbMonster aquí podría escribirse de forma más idiomática.
Complejidad
Tanto React como Mithril.js tienen superficies de API relativamente pequeñas en comparación con otros frameworks, lo que ayuda a facilitar la curva de aprendizaje. Sin embargo, mientras que Mithril.js idiomático se puede escribir sin pérdida de legibilidad usando ES5 plano y sin otras dependencias, React idiomático depende en gran medida de herramientas complejas (por ejemplo, Babel, plugin JSX, etc.), y este nivel de complejidad se extiende con frecuencia a partes populares de su ecosistema, ya sea en forma de extensiones de sintaxis (por ejemplo, sintaxis no estándar de propagación de objetos en Redux), arquitecturas (por ejemplo, las que usan librerías de datos inmutables) o extras (por ejemplo, recarga de módulos en caliente).
Si bien las cadenas de herramientas complejas también son posibles con Mithril.js y otros frameworks, se recomienda encarecidamente seguir los principios KISS y YAGNI al usar Mithril.
Curva de aprendizaje
Tanto React como Mithril.js tienen curvas de aprendizaje relativamente pequeñas. La curva de aprendizaje de React implica principalmente la comprensión de los componentes y su ciclo de vida. La curva de aprendizaje para los componentes de Mithril.js es casi idéntica. Obviamente, hay más APIs para aprender en Mithril.js, ya que Mithril.js también incluye enrutamiento y XHR, pero la curva de aprendizaje sería bastante similar a aprender React, React Router y una librería XHR como superagent o axios.
React idiomático requiere un conocimiento práctico de JSX y sus advertencias y, por lo tanto, también hay una pequeña curva de aprendizaje relacionada con Babel.
Documentación
La documentación de React es clara y está bien escrita, e incluye una buena referencia de la API, tutoriales para empezar, así como páginas que cubren varios conceptos avanzados. Desafortunadamente, dado que React se limita a ser solo una librería de vistas, su documentación no explora cómo usar React idiomáticamente en el contexto de una aplicación de la vida real. Como resultado, hay muchas librerías de gestión de estado populares y, por lo tanto, las arquitecturas que usan React pueden diferir drásticamente de una empresa a otra (o incluso entre proyectos).
La documentación de Mithril.js también incluye tutoriales introductorios, páginas sobre conceptos avanzados y una extensa sección de referencia de la API, que incluye información sobre el tipo de entrada/salida, ejemplos para varios casos de uso comunes y consejos contra el uso indebido y los antipatrones. También incluye un resumen rápido para una referencia rápida.
La documentación de Mithril.js también demuestra soluciones simples y cercanas al metal (de bajo nivel) para casos de uso comunes en aplicaciones de la vida real donde es apropiado informar a un desarrollador que los estándares web pueden estar ahora a la par con las librerías establecidas más grandes.
Angular
Angular es un framework de aplicaciones web mantenido por Google.
Angular y Mithril.js son bastante diferentes, pero comparten algunas similitudes:
- Ambos soportan la componentización.
- Ambos tienen una serie de herramientas para varios aspectos de las aplicaciones web (por ejemplo, enrutamiento, XHR).
La diferencia más obvia entre Angular y Mithril.js está en su complejidad. Esto se puede ver más fácilmente en cómo se implementan las vistas. Las vistas de Mithril.js son JavaScript plano, y el control de flujo se realiza con mecanismos incorporados de JavaScript como operadores ternarios o Array.prototype.map
. Angular, por otro lado, implementa un sistema de directivas para extender las vistas HTML de modo que sea posible evaluar expresiones similares a JavaScript dentro de los atributos e interpolaciones HTML. Angular realmente se envía con un analizador y un compilador escritos en JavaScript para lograr eso. Si eso no parece lo suficientemente complejo, en realidad hay dos modos de compilación (un modo predeterminado que genera funciones JavaScript dinámicamente para el rendimiento, y un modo más lento para lidiar con las restricciones de la Política de seguridad de contenido).
Rendimiento
Angular ha mejorado significativamente su rendimiento a lo largo de los años. Angular 1 usaba un mecanismo conocido como comprobación sucia (dirty checking) que tendía a volverse lento debido a la necesidad de diferenciar constantemente las grandes estructuras $scope
. Angular 2 usa un mecanismo de detección de cambios de plantilla que es mucho más eficiente. Sin embargo, incluso a pesar de las mejoras de Angular, Mithril.js suele ser más rápido que Angular, debido a la facilidad de revisión que permite el pequeño tamaño de la base de código de Mithril.js.
Es difícil comparar los tiempos de carga entre Angular y Mithril.js por varias razones. La primera es que Angular 1 y 2 son, de hecho, bases de código completamente diferentes, y ambas versiones son oficialmente compatibles y mantenidas (y la gran mayoría de las bases de código de Angular en el mundo real actualmente todavía usan la versión 1). La segunda razón es que tanto Angular como Mithril.js son modulares. En ambos casos, es posible eliminar una parte significativa del framework que no se utiliza en una aplicación determinada.
Dicho esto, el paquete Angular 2 más pequeño conocido es un hello world de 29kb comprimido con el algoritmo Brotli (son 35kb usando gzip estándar), y con la mayor parte de la funcionalidad útil de Angular eliminada. En comparación, un hello world de Mithril.js - incluyendo todo el núcleo de Mithril.js con baterías y todo - sería de unos 10kb comprimido con gzip.
Además, recuerda que frameworks como Angular y Mithril.js están diseñados para aplicaciones no triviales, por lo que una aplicación que lograra usar toda la superficie de la API de Angular necesitaría descargar varios cientos de kb de código de framework, en lugar de simplemente 29kb.
Rendimiento de actualización
Una herramienta útil para comparar el rendimiento de la actualización es una herramienta desarrollada por el equipo de Ember llamada DbMonster. Actualiza una tabla tan rápido como puede y mide los fotogramas por segundo (FPS) y los tiempos de JavaScript (mínimo, máximo y medio). El recuento de FPS puede ser difícil de evaluar, ya que también incluye los tiempos de repintado del navegador y la latencia introducida por setTimeout
, por lo que el tiempo medio de renderización es el dato más relevante. Puedes comparar una implementación de Angular y una implementación de Mithril.js. Los resultados de la muestra se muestran a continuación:
Angular | Mithril.js |
---|---|
11.5 ms | 6.4 ms |
Complejidad
Angular es superior a Mithril.js en la cantidad de herramientas que ofrece (en forma de varias directivas y servicios), pero también es mucho más complejo. Compare la superficie de la API de Angular con la de Mithril.js. Puedes hacer tu propio juicio sobre qué API es más auto-descriptiva y más relevante para tus necesidades.
Angular 2 tiene muchos más conceptos para entender: a nivel de lenguaje, TypeScript es el lenguaje recomendado, y además de eso también hay una sintaxis de plantilla específica de Angular, como enlaces, pipes, "operador de navegación segura". También necesitas aprender sobre conceptos arquitectónicos como módulos, componentes, servicios, directivas, etc., y dónde es apropiado usar qué.
Curva de aprendizaje
Si comparamos manzanas con manzanas, Angular 2 y Mithril.js tienen curvas de aprendizaje similares: en ambos, los componentes son un aspecto central de la arquitectura, y ambos tienen herramientas razonables de enrutamiento y XHR.
Dicho esto, Angular tiene muchos más conceptos para aprender que Mithril. Ofrece APIs específicas de Angular para muchas cosas que a menudo se pueden implementar trivialmente (por ejemplo, la pluralización es esencialmente una sentencia switch, la validación "requerida" es simplemente una comprobación de igualdad, etc.). Las plantillas de Angular también tienen varias capas de abstracciones para emular lo que JavaScript hace de forma nativa en Mithril.js - ng-if
/ngIf
de Angular es una directiva, que utiliza un analizador y un compilador personalizados para analizar una cadena de expresión y emular el alcance léxico... y así sucesivamente. Mithril.js tiende a ser mucho más transparente y, por lo tanto, más fácil de razonar.
Documentación
La documentación de Angular 2 proporciona un extenso tutorial introductorio y otro tutorial que implementa una aplicación. También tiene varias guías para conceptos avanzados, un resumen rápido y una guía de estilo. Desafortunadamente, por el momento, la referencia de la API deja mucho que desear. Varias APIs no están documentadas o no proporcionan ningún contexto para lo que podría usarse la API.
La documentación de Mithril.js incluye tutoriales introductorios, páginas sobre conceptos avanzados y una extensa sección de referencia de la API, que incluye información sobre el tipo de entrada/salida, ejemplos para varios casos de uso comunes y consejos contra el uso indebido y los antipatrones. También incluye un resumen rápido para una referencia rápida.
La documentación de Mithril.js también demuestra soluciones simples y cercanas al metal (de bajo nivel) para casos de uso comunes en aplicaciones de la vida real donde es apropiado informar a un desarrollador que los estándares web pueden estar ahora a la par con las librerías establecidas más grandes.
Vue
Vue es una librería de vistas similar a Angular.
Vue y Mithril.js tienen muchas diferencias, pero también comparten algunas similitudes:
- Ambos usan DOM virtual y métodos de ciclo de vida.
- Ambos organizan las vistas a través de componentes.
Vue 2 usa una bifurcación de Snabbdom como su sistema de DOM virtual. Además, Vue también proporciona herramientas para el enrutamiento y la gestión del estado como módulos separados. Vue se parece mucho a Angular y proporciona un sistema de directivas similar, plantillas basadas en HTML y directivas de flujo lógico. Se diferencia de Angular en que implementa un sistema reactivo de monkeypatching (modificación dinámica de código) que sobrescribe los métodos nativos en el árbol de datos de un componente (mientras que Angular 1 usa la comprobación sucia y los ciclos de digest/apply para lograr resultados similares). Similar a Angular 2, Vue compila plantillas HTML en funciones, pero las funciones compiladas se parecen más a las vistas de Mithril.js o React, que a las funciones de renderización compiladas de Angular.
Vue es significativamente más pequeño que Angular cuando se comparan manzanas con manzanas, pero no tan pequeño como Mithril.js (el núcleo de Vue es de alrededor de 23kb comprimido con gzip, mientras que el módulo de renderización equivalente en Mithril.js es de alrededor de 4kb comprimido con gzip). Ambos tienen características de rendimiento similares, pero las pruebas comparativas generalmente sugieren que Mithril.js es ligeramente más rápido.
Rendimiento
Aquí hay una comparación de los tiempos de carga de la librería, es decir, el tiempo que se tarda en analizar y ejecutar el código JavaScript para cada framework, añadiendo una llamada console.time()
en la primera línea y una llamada console.timeEnd()
en la última de un script que se compone únicamente de código de framework. Para facilitar la lectura, se presentan los mejores resultados de 20 pruebas, donde se añadió manualmente código de registro a los scripts empaquetados. Las pruebas se realizaron en Chrome, desde el sistema de archivos, en un PC de escritorio de 2010.
Vue | Mithril.js |
---|---|
21.8 ms | 4.5 ms |
Los tiempos de carga de la librería son importantes en las aplicaciones que no permanecen abiertas durante largos periodos de tiempo (por ejemplo, cualquier cosa en el móvil) y no pueden mejorarse mediante el almacenamiento en caché u otras técnicas de optimización.
Rendimiento de actualización
Una herramienta útil para comparar el rendimiento de la actualización es una herramienta desarrollada por el equipo de Ember llamada DbMonster. Actualiza una tabla tan rápido como puede y mide los fotogramas por segundo (FPS) y los tiempos de JavaScript (mínimo, máximo y medio). El recuento de FPS puede ser difícil de evaluar, ya que también incluye los tiempos de repintado del navegador y la latencia introducida por setTimeout
, por lo que el tiempo medio de renderización es el dato más relevante. Puedes comparar una implementación de Vue y una implementación de Mithril.js. Los resultados de la muestra se muestran a continuación:
Vue | Mithril.js |
---|---|
9.8 ms | 6.4 ms |
Complejidad
Vue está fuertemente inspirado en Angular y tiene muchas cosas que Angular hace (por ejemplo, directivas, filtros, enlaces bidireccionales, v-cloak
), pero también tiene cosas inspiradas en React (por ejemplo, componentes). A partir de Vue 2.0, también es posible escribir plantillas usando la sintaxis hyperscript/JSX (además de los componentes de un solo archivo y los diversos plugins de transpilación de lenguaje basados en webpack). Vue proporciona tanto el enlace de datos bidireccional como una librería opcional de gestión de estado similar a Redux, pero a diferencia de Angular, no proporciona una guía de estilo. La flexibilidad de elegir entre varias opciones para realizar la misma tarea puede llevar a una fragmentación arquitectónica en proyectos a largo plazo.
Mithril.js tiene muchos menos conceptos y normalmente organiza las aplicaciones en términos de componentes y una capa de datos. Todos los estilos de creación de componentes en Mithril.js generan la misma estructura vnode utilizando solo características nativas de JavaScript. La consecuencia directa de apoyarse en el lenguaje es menos herramientas y una configuración de proyecto más simple.
Documentación
Tanto Vue como Mithril.js tienen buena documentación. Ambos incluyen una buena referencia de la API con ejemplos, tutoriales para empezar, así como páginas que cubren varios conceptos avanzados.
Sin embargo, debido al enfoque de muchas maneras de hacer una cosa de Vue, algunas cosas pueden no estar adecuadamente documentadas. Por ejemplo, su hyperscript se pasa por alto en gran medida.
La documentación de Mithril.js normalmente suele ser muy detallada, incluso cuando un tema involucra elementos que están fuera del alcance del framework. Por ejemplo, cuando un tema involucra una librería de terceros, la documentación de Mithril.js recorre el proceso de instalación de la librería de terceros. La documentación de Mithril.js también demuestra a menudo soluciones simples y cercanas al metal (de bajo nivel) para casos de uso comunes en aplicaciones de la vida real donde es apropiado informar a un desarrollador que los estándares web pueden estar ahora a la par con las librerías establecidas más grandes.
Los tutoriales de Mithril.js también cubren mucho más terreno que los de Vue: el tutorial de Vue termina con una simple lista de tareas local, después de pasar por varias páginas para cubrir su gran API central. La guía de 10 minutos de Mithril.js cubre la mayoría de su API e incluso repasa los aspectos clave de las aplicaciones de la vida real, como la obtención de datos de un servidor y el enrutamiento. Si eso no es suficiente, también hay un tutorial más largo y completo.