Hace aproximadamente un año, se publicó el artículo manifiesto de Nikita Prokopov sobre la decepción en el software. A juzgar por los comentarios positivos, los desarrolladores no son indiferentes a la calidad de sus productos. ¿Quizás es hora de comenzar a actuar?
En este artículo quiero hablar sobre mi desarrollo, que, en mi opinión, puede curar los principales problemas de rendimiento de la web moderna y hacer que el usuario esté un poco más feliz. Los problemas son: código JS pesado, alto tiempo para comenzar a trabajar con la página (TTI) , alto consumo de memoria y procesador.
Antes de seguir leyendo, siga el enlace . Intenta jugar un par de juegos. Juega preferiblemente desde el escritorio.
Un poco de historia
Desde el principio, el navegador web fue concebido como un cliente ligero para servidores web. El navegador muestra las páginas de hipertexto que recibió del servidor. Simple y elegante Como suele suceder, una hermosa idea se enfrenta a la realidad, y después de unos años, los fabricantes de navegadores han agregado soporte para el lenguaje de secuencias de comandos. Al principio, solo servía como decoración, y hasta mediados de la década de 2000, se consideraba una buena forma de hacer que las páginas web funcionaran sin el soporte de JS.
Un enfoque moderno para el desarrollo de sitios web es el resultado del desarrollo de los requisitos de interactividad de la interfaz de usuario. Las tareas para mejorar la interactividad recayeron en los hombros de los codificadores. Esos a menudo no tenían las competencias y la autoridad para desarrollar una solución "de extremo a extremo". Los diseñadores de diseño aprendieron a escribir JS y se convirtieron en front-end. La lógica comenzó a fluir gradualmente del servidor al cliente. Es conveniente para el favorito escribir para el navegador, y el back-end es conveniente para no pensar en el usuario (darle mi JSON, y al menos la hierba no crece). Hace solo dos años, hubo un gran interés en la arquitectura sin servidor, donde se sugirió que las aplicaciones JS trabajarían directamente con la base de datos y los buses de eventos.
Actualmente, un "sitio web esférico en el vacío" es una aplicación JS compleja y un servidor API simple con el que se comunica. La lógica principal se ejecuta en un cliente grueso, el lado del servidor degenera en una capa simple de la base de datos.
La necesidad de mantener la lógica en el cliente crea problemas. Si el servicio "despegó" y comenzó a ganar dinero, además, en términos de productividad, solo empeorará. Los requisitos cambiarán. El equipo de desarrollo cambiará. Habrá más y más código nuevo, y el código antiguo no se limpiará. La página se hinchará de dependencias, cargará JSON sobre el propósito del que nadie recuerda, pero da miedo eliminarlo, de repente algo se rompe. Aparecerán las tareas de fondo SetInterval, cada una de las cuales se realiza durante varios milisegundos por segundo, lo que después de un tiempo provocará frenos y calentará el iPad del desafortunado usuario hasta el punto de que pueda freír huevos fritos en él. Termina con el hecho de que el front-end quemado llegará al gerente con una propuesta para reescribir todo desde cero en un nuevo marco. El gerente se negará, y el front-end comenzará a usar dos marcos juntos.
¿Cómo funciona Korolev?
Entonces, ¿qué pasa si volvemos al punto del informe? ¿El momento en que a alguien se le ocurrió la idea de actualizar el contenido sin volver a cargar la página, y la inevitabilidad histórica dio lugar a AJAX? ¿Qué sucede si deja todo en el servidor y crea un cliente ligero? Los mejores sitios realizan la representación previa de la página del servidor (SSR) para que el usuario vea la interfaz antes de que JS se cargue y comience. Puede ir más allá y dejar en el cliente solo el código responsable del procesamiento de E / S, dados los requisitos actuales de interactividad. Los pensamientos sobre esto se extendieron al proyecto Korolev .
¿Cómo funciona en el lado del cliente? El usuario llega a la página. El servidor proporciona el HTML generado y un pequeño script (~ 6 Kbytes sin compresión) que se conecta al servidor a través de un socket web. Cuando un usuario dispara un evento (por ejemplo, un clic), el script lo envía al servidor. Una vez procesado el evento, el servidor genera una lista de comandos de la forma "agregar un nuevo <div>
allí", "agregar una clase a dicho elemento", "eliminar tal y tal elemento". El cliente aplica la lista de comandos al DOM. Como tal, el trabajo con HTML no se produce: el script funciona directamente con el DOM, por lo que no debe preocuparse de que se restablezca el contenido del formulario o la posición del desplazamiento.
¿Qué está pasando en el servidor? Cuando una solicitud de una página proviene del navegador, Korolev crea una nueva sesión. Para la sesión, se realiza el estado inicial, que se almacena en la memoria caché. El HTML se genera a partir de este estado, que se entrega al cliente como respuesta a la solicitud. Además, el servidor guarda el "DOM virtual" en la sesión. Después de solicitar la página, el servidor acepta la solicitud de abrir el socket web. Korolev asocia un socket web abierto con una sesión. Cada evento proveniente del cliente puede cambiar el estado asociado con la sesión. Cada cambio de estado conduce a una llamada a la función de render
, que forma un nuevo "DOM virtual", que se compara con la versión anterior. La comparación da como resultado una lista de comandos para enviar al cliente.
¿Qué pasa en el código y jefe del desarrollador? Lo anterior podría recordarle a React, con la diferencia de que todo se ejecuta en el servidor. En términos de enfoque de desarrollo, también tenemos algo similar. Por lo tanto, si trabajó con React u otro "DOM virtual", el enfoque de la Reina le resultará familiar. Si no está familiarizado con React, imagine que tiene datos que inserta en la plantilla. Imagine que, según la plantilla, los controladores de eventos están dispersos y pueden cambiar los datos (pero no el DOM). Cambias los datos, la página se cambia a sí misma. A Korolev se le ocurre cómo cambiar el DOM.
Rendimiento
Hay dos preguntas populares sobre Korolev: "¿y si los retrasos son altos" y "esto no cargará mi servidor"? Ambas preguntas son muy razonables. El programador front-end está acostumbrado a que su programa se ejecute en la máquina local del usuario. Esto significa que los cambios realizados se aplicarán tan pronto como la máquina JS termine de ejecutar el código y el navegador comience a procesar. Mostré específicamente un ejemplo de uso "a la velocidad máxima" al principio. Puede observar la demora solo si vino del otro lado del mundo (los servidores están ubicados en Moscú) o si se sentó en Internet a través de GPRS. Bueno, o mi patético servidor virtual con un núcleo y 1 GB de RAM no pudo soportar el efecto habr.
La pregunta sobre la carga del servidor generalmente la hacen los beckenders. El motor de salida de cambios funciona muy rápidamente: ~ 10 mil conclusiones por segundo para dos árboles arbitrarios de 500 nodos en el macbook junior de 2013. La representación estática también ofrece un resultado bastante bueno: hasta 1 millón de páginas por segundo. Cada "DOM virtual" se almacena y procesa en una forma serializada especial y ocupa 128 KB para una página web promedio. El proceso de salida está especialmente optimizado y no tiene una sobrecarga para la memoria y el GC.
En cuanto a la velocidad de desarrollo, aquí Korolev ofrece grandes ventajas. No es necesario escribir una capa adicional entre la base de datos y el servidor. No es necesario negociar un protocolo entre el cliente y el servidor. No necesita preocuparse por la modularidad del front-end: el peso JS en el cliente siempre será el mismo. No es necesario hacer una lógica adicional para los eventos del servidor: solo acepte el mensaje de la cola y cambie el estado de la sesión, Korolev lo procesará y entregará.
Precio
Tienes que pagar por los beneficios. Algunos hábitos tendrán que ser abandonados, y algunos nuevos para adquirir. Por ejemplo, debe abandonar las animaciones JS y estar satisfecho con las animaciones CSS. Tendrá que aprender cómo hacer que la infraestructura sea inicialmente geo-distribuida si desea servir a los usuarios de diferentes países con alta calidad. Tienes que abandonar JS e ir a Scala.
Estoy un poco avergonzado (en realidad no) de haber engañado al lector y no dije de inmediato que Korolev fue escrito en Scala. ¿Podrías leer hasta este punto si inmediatamente hablara sobre esto? Hablando de la Reina, tengo que superar dos estereotipos. El primero se debe al hecho de que la representación del servidor se percibe como algo lento, no interactivo. El segundo está relacionado con el hecho de que Scala es algo complicado. Y el primer y segundo estereotipo no tienen nada que ver con la realidad. Además, la programación en estilo React en Scala es más conveniente que en JS. JS moderno gravita hacia la programación funcional, Scala lo saca de la caja. Por ejemplo, cualquier objeto en Scala tiene un método copy()
que le permite copiar un objeto cambiando algunos campos. Las colecciones inmutables están integradas en la biblioteca estándar de Scala.
Conclusión
Korolev ha sido desarrollado durante tres años por varios desarrolladores y muchos problemas "infantiles" se resuelven en él. El proyecto está bien documentado, toda la funcionalidad está cubierta con ejemplos. Propongo comenzar la implementación de la Reina con pequeños servicios independientes. Espero que Korolev ayude a que los programas sean menos decepcionantes.
Enlace al proyecto en github