Lo nuevo en la versión Angular 8

Así que salió angular 8, incluye una vista previa de Ivy, soporte para trabajadores de servicio, carga diferencial y algunos otros toques finales. Manfred Steyer explica los cambios más importantes en la última versión.

Según lo planeado, no hubo sorpresas: la actualización del marco y la CLI se pueden hacer usando ng update, y las nuevas características son una buena adición al lema "evolución en lugar de revolución".

En este artículo, el autor habla sobre las nuevas características más importantes de Angular 8 y Angular CLI 8. Los ejemplos utilizados en el artículo se pueden encontrar en GitHub .

Debajo del corte:


  • Primer vistazo a Ivy
  • Trabajadores web
  • Carga diferencial
  • Módulos de carga diferidos
  • Cambios críticos en ViewChild y ContentChild
  • Nuevas funciones ngUpgrade


Primer vistazo a Ivy


La próxima gran noticia que la comunidad Angular está esperando es Ivy, un nuevo compilador, y también un nuevo motor de renderizado. Ivy puede generar paquetes significativamente más pequeños, compilación incremental, y también es la base para la innovación futura en Angular.

Dado que muchas de las partes básicas de Angular se han cambiado, el equipo de Angular ha prestado especial atención a la compatibilidad con versiones anteriores: después de actualizar a Ivy, las aplicaciones existentes deberían funcionar de la misma manera que antes. En el mejor de los casos, obtendrá paquetes mucho más pequeños. Esto no es desinteresado, ya que más de 600 aplicaciones en Google se basan oficialmente en Angular: se rumorea que el número real es mucho mayor.

Con Angular 8, una versión preliminar de Ivy está disponible para pruebas. El propósito de esta versión es obtener comentarios rápidos. Por lo tanto, el equipo angular recomienda no usar Ivy en el producto en este momento, sino continuar usando el motor de vista clásico (Fig. 1)


Gracias a la carga diferencial (como se ve a continuación), los tamaños de paquete se pueden optimizar en este momento.

Según Brad Green, CTO del equipo de Angular en Google, en ngconf 2019, Ivy mejorará significativamente los tamaños de paquete en modo de compatibilidad, combinado con carga diferencial. Por lo tanto, los temerarios ya pueden probar la futura API de Ivy. Este modo, en particular, tiene un gran potencial para la optimización. La API todavía está marcada como privada. Mirando sus clases y funciones, puede decir: comienzan con un símbolo especial ɵ.

Si ya quieres probar Ivy, puedes crear un nuevo proyecto con el interruptor enable-ivy:
ng new ivy-project --enable-ivy 

Esta clave le dice a la CLI que guarde la siguiente entrada en la configuración tsconfig.app.json:
 "angularCompilerOptions": { "enableIvy": true } 

Esta entrada también se puede agregar manualmente después de actualizar a la versión 8, para probar una aplicación existente con Ivy.
Para ejecutar la aplicación en modo de depuración, se recomienda usar AOT:
 ng serve --aot 

Además, debe prestar atención al tamaño de la aplicación creada usando ng build. Con angular 9, Ivy debería activarse por defecto. Hasta entonces, el equipo de Angular planea continuar trabajando para garantizar la compatibilidad con versiones anteriores.

Trabajadores web


JavaScript es de un solo subproceso por definición. Debido a esto, las tareas que consumen mucho tiempo, como la consulta de datos, generalmente se realizan de forma asincrónica. No hace falta decir que esto no ayuda en cálculos complejos. Se están volviendo especialmente comunes con las amplias soluciones de JavaScript, por lo que apoyamos a los trabajadores web en casi todos los navegadores web. Estos son scripts que el navegador inicia en un hilo separado. La comunicación con la transmisión en la pestaña del navegador se realiza a través de mensajes.
Aunque los trabajadores web no están relacionados con Angular como tal, deben tenerse en cuenta al construir. El objetivo es proporcionar un paquete para cada trabajador web. Esta tarea ha sido completada por la nueva CLI.
Para demostrar una nueva característica, le mostraré a JavaScript la implementación del llamado " problema de las reinas n ". La idea es colocar una reina en una fila en un tablero de ajedrez, sin poder amenazarse mutuamente. Esto significa que en la misma fila, columna o diagonal no debería ser otra reina.

El algoritmo para calcular todas las soluciones posibles en un tablero de ajedrez se considera computacionalmente complejo. Aunque los cálculos para un tablero de ajedrez regular de ocho filas y ocho columnas son bastante rápidos, las computadoras convencionales han alcanzado el límite con un tablero de 12 x 12. La solución para un tablero de 27 x 27 es el récord actual. Para esta tarea, se utilizaron supercomputadoras rusas.
Para traducir este cálculo en segundo plano, primero debemos crear un trabajador web utilizando la CLI:
 ng generate worker n-queens 

Esta instrucción crea un archivo no solo para el empleado, sino también para los archivos de configuración necesarios para el proceso de compilación y las entradas en los archivos existentes. Si la misma carpeta contiene un componente con el mismo nombre con una extensión de archivo .component.ts común, la CLI también agregará código para interactuar con el trabajador web.
El trabajador en sí consiste en un oyente para el evento:
 import nQueens from './n-queens'; addEventListener('message', ({ data }) => { const result = nQueens(data.count); postMessage(result, undefined); }); 

El evento se ejecuta cuando el hilo principal envía un mensaje al trabajador. El parámetro contiene información enviada desde la secuencia principal. En este caso, está limitado por la propiedad count, que establece el tamaño del tablero de ajedrez. Después de evaluar la función nQueens, que se omite aquí, eventListener envía el resultado al hilo principal a través de postMessage. Por lo tanto, el navegador dispara un evento de mensaje.
La clase Worker se usa en el componente using para interactuar con el script de trabajo:
 const count = parseInt(this.count, 10); const worker = new Worker('../logic/n-queens.worker', { type: 'module' // Worker uses EcmaScript modules }); worker.postMessage({count}); worker.addEventListener('message', (event) => { // tslint:disable-next-line: no-console console.debug('worker result', event.data); // Update chessboard this.processResult(event.data); }); 

El componente envía un mensaje con el tamaño deseado del tablero de ajedrez al trabajador a través de postMessage y, por lo tanto, comienza el cálculo allí. Recibe el resultado a través del mensaje de evento.
En el futuro, la CLI se encarga del correcto ensamblaje de los scripts de trabajo. El compilador TypeScript los reconoce al final de .worker.ts, que está registrado en tsconfig.worker.json creado por el comando ng generate worker . Para asegurarse de que la CLI no afecte estos archivos nuevamente al compilar la aplicación principal, ng generate worker coloca la misma plantilla de archivo en la sección de exclusión de tsconfig.app.json.
La implementación completa está en el proyecto con ejemplos del autor. A modo de comparación, un ejemplo de la tarea N queens se puede resolver tanto en el hilo principal como en el trabajador web. Cuando intente resolver un problema para un tablero de ajedrez de 12 x 12, por ejemplo, verá que la interfaz de usuario se bloquea en el primer caso, mientras que el cálculo de fondo con el trabajador web no reducirá el rendimiento.

Carga diferencial


Hasta ahora, era costumbre compilar aplicaciones en el viejo ES 5, ya que esta versión de "JavaScript de nuestros padres" funciona en casi todas partes. Esto significa que tanto IE11 como el rastreador web de Google pueden ejecutar este código.
Sin embargo, el nuevo ES 2015 y sus versiones posteriores son más eficientes: le permiten crear paquetes más compactos y el navegador también puede interpretarlos de manera más eficiente. Como anteriormente era habitual volver a ES 5 como el denominador menos común, los navegadores modernos, desafortunadamente, no pudieron aprovechar la nueva versión del lenguaje.
Ahora se acabó: a partir de la versión 8, la CLI tiene una característica llamada carga diferencial. La idea es proporcionar dos grupos de paquetes: uno basado en ECMAScript 5 y diseñado para navegadores antiguos, el otro basado en una nueva versión de ECMAScript, como ECMAScript 2015, y proporciona navegadores modernos con los beneficios mencionados anteriormente.
No necesita hacer mucho trabajo para habilitar la carga diferencial: todo lo que se necesita es establecer los límites superior e inferior de las versiones compatibles de ECMAScript. El límite superior se indica en tsconfig.json de la siguiente manera:
 "target": "es2015" 

El límite inferior se define en el archivo de la lista de navegadores. Este archivo incluye navegadores que serán compatibles de acuerdo con ciertos criterios, como la participación de mercado, por ejemplo. Se pueden guardar, por ejemplo, en el archivo de la lista de navegadores, que la CLI crea en la raíz del proyecto al crear un nuevo proyecto:
> 0.5%
last 2 versions
Firefox ESR
not dead
IE 9-11

En este caso, la lista de navegadores incluye los navegadores ES 5 con una entrada IE 9-11. Por lo tanto, la CLI define el umbral inferior como esta versión. Cuando la CLI recibe el comando ng build, el proceso de compilación se ejecutará para ambas versiones:

La desventaja de este proceso es la siguiente: el tiempo requerido para el montaje se duplica.
Los navegadores ahora pueden decidir qué versión de paquetes descargar. Para hacer esto, obtienen enlaces a scripts en el complemento index.html: aquellos que apuntan a paquetes ECMAScript 5 reciben la adición de un nomodule. Por lo tanto, los navegadores con soporte ECMAScript y, por lo tanto, soporte ECMAScript 2015+ no ignorarán este script. Por otro lado, la CLI implementa los paquetes ECMAScript 2015+ con type = "module". Por lo tanto, los navegadores antiguos ignorarán estos scripts:
 <script src="main-es2015.js" type="module"></script> <script src="main-es5.js" nomodule></script> 

A diferencia de ng build, el resto de los comandos de la CLI solo usan (!) El límite superior de compatibilidad con ES. En nuestro caso, esto es ECMAScript 2015. Esto sucede, incluso por razones de eficiencia: durante la depuración y las pruebas, los desarrolladores generalmente quieren ver el resultado lo antes posible, sin esperar la segunda compilación.

Módulos de carga diferidos


Desde los primeros días, el enrutador angular admite la carga diferida. Hasta ahora, esto se ha logrado con la definición mágica de un módulo cargable:
 { path: 'lazy', loadChildren: () => './lazy/lazy.module#LayzModule' } 

El valor antes de # describe la ruta que conduce al archivo de implementación del módulo; el valor después significa la clase que contiene. Este estilo de descripción funciona en Angular 8, pero ha quedado en desuso en relación con las importaciones dinámicas ECMAScript:
 { path: 'lazy', loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule) } 

La nueva opción de registro aún contiene el nombre del archivo como un valor mágico. Sin embargo, dado que las importaciones son compatibles con muchos IDE, los valores no válidos devolverán inmediatamente un error.

Cambios críticos en ViewChild y ContentChild


Hay cambios críticos en el uso de ViewChild y ContentChild, que, desafortunadamente, en el pasado no siempre funcionaban de manera predecible. Si en versiones anteriores fueron utilizados por un componente para consultar elementos que no están dentro de una directiva estructural, como ngIf o ngFor, el resultado de la consulta ya estaba disponible en ngOnInit. De lo contrario, podríamos acceder a ellos no antes de ngAfterViewInit (o ngAfterContentInit para ContentChild). Para los elementos que se cargaron en el DOM más tarde debido al enlace de datos, el código del programa debería tener ngAfterViewChecked o, en consecuencia, ngAfterContentChecked.
Dado que este comportamiento era confuso, el componente ahora debería indicar cuándo debería ocurrir la resolución:
 @ViewChild('info', { static: false }) paragraph: ElementRef; 

Si el indicador estático es verdadero, Angular intentará encontrar los elementos cuando se inicialice el componente. Esto solo funciona si no están en la directiva estructural. Cuando se utiliza static: false, la resolución se realiza después de inicializar o actualizar la vista.
ng update intentará ingresar automáticamente el valor correcto, si esto no es posible, agregará un comentario con TODO.
Este cambio no afectará las consultas con los decoradores ViewChildren y ContentChildren. Siempre tuvieron un comportamiento dinámico, en términos nuevos en el sentido de estático: falso.

Nuevas funciones ngUpgrade


Hasta ahora, uno de los problemas con AngularJS 1.X y Angular mezclado con ngUpgrade era que los enrutadores de ambos frameworks estaban compitiendo debido a la URL. Esto condujo a efectos secundarios difíciles de explicar. Para evitar esto, se agregó la capacidad de utilizar un único servicio de ubicación de URL en ambas versiones.
Para hacer esto, el equipo de Angular amplió las capacidades de los servicios de ubicación Angular y, por lo tanto, proporcionó un reemplazo para $ location en AngularJS.
Por esta razón, se ha agregado un nuevo método onUrlChange al servicio de ubicación para rastrear los cambios de URL:
 export class AppComponent { constructor(loc: Location, pLoc: PlatformLocation) { loc.onUrlChange((url) => console.debug('url change', url)); console.debug('hostname: ', pLoc.hostname); } } 

El servicio PlatformLocation ofrece acceso adicional a partes específicas de la URL. Aquí puede encontrar una descripción detallada de cómo se usa el reemplazo de $ location basado en él para integrar mejor los marcos. Además, ahora puede encontrar la solución de carga diferida AngularJS, que se basa en la importación dinámica de ECMAScript antes mencionada.

Conclusión


Nuevamente, el equipo de Angular mantuvo su palabra: la transición a la nueva versión de Angular es simple y no incluye cambios importantes. Por el contrario, se suavizaron algunas esquinas, lo que hizo que trabajar con el marco SPA de Google fuera aún más cómodo. La carga diferencial proporciona oportunidades para una mayor optimización de los tamaños de paquetes si los navegadores más antiguos no son compatibles o no son compatibles con paquetes separados. El soporte para el trabajador web muestra que las tareas computacionalmente intensivas encuentran su camino al procesamiento en el navegador. Los entusiastas ahora pueden dar sus primeros pasos con Ivy.

PD: Esta es mi primera traducción, así que tenga en cuenta los comentarios, sugerencias y errores en los comentarios.

Source: https://habr.com/ru/post/455493/


All Articles