¿Qué trae nuevo Angular 17 💞? Novedades, instalar y migrar

Publicado el 11.11.2023 a las 00:24

¿Qué trae nuevo Angular 17 💞? Novedades, instalar y migrar

  1. ¿Novedades de la versión 17 de Angular? 💣

    • Bienvenido SSR a Angular 😍

    • Compiladores en Angular 17

    • ¿Cómo eligo el compilador en Angular 17?

    • ¿Cómo configuro el SSR?

    • Nueva sintaxis if else

    • Nueva sintaxis switch

    • Nueva sintaxis for

    • Vistas diferidas o defer views (lazy loading)

    • Defer triggers en Angular 17

    • Migrar a la nueva sintaxis automáticamente

    • Nueva web y documentación

  2. ¿Cómo sabemos con qué versión de Angular estamos trabajando?

    • Con el package.json

    • Ejecutando la aplicación

    • Con el CLI

  3. ¿Cómo actualizar/migrar a Angular 17?

  4. Actualizar Angular CLI globalmente

  5. Posibles errores

    • Package '@angular/core' is not a dependency

  6. Cuando todo falla

¿Qué trae nuevo Angular 17 💞? Novedades, instalar y migrar

Esta semana han liberado la versión 17 de Angular, y si me gustó la 16 te adelanto que la 17 es una locura 💣. Te cuento cómo instalar la versión 17, cómo migrar tus proyectos de la versión 16 a la 17 y la novedades de la versión 17 de Angular


Hacía mucho tiempo que no me encontraba ansioso por programar y la nueva versión de Angular, la 17, ha conseguido que me vuelva esa pasión 💘


¿No me crees? Estoy escribiendo este artículo y probando la versión 17 de Angular un viernes por la noche.

Como decía mi abuelo...

Para muestra, un botón

Me gusta mucho programar, un pasatiempo que tengo es resolver pequeños ejercicios de algoritmia tipo advent of code.


Cuando me tocaba programar con Angular había cosillas que se me atravesaban.

Esta nueva versión ha conseguido que todas esas cosillas que me molestaban dejen de estar 🤯


¿Cómo Angular sabía lo que me molestaba?


Angular nos hizo una encuesta a su comunidad y por lo visto... lo que a mí me molestaba también le molestaba a la mayoría.


Te cuento 👇

¿Qué trae nuevo Angular 17?

Si en mi artículo de Angular 16 te decía que era la versión de Angular que más ilusión me hacía...

Imagen del artículo

Angular 16, una super versión 🦸‍♂️

¿Por qué para mí Angular 16 es una super versión?, ¿Quieres instalar Angular 16?, ¿quieres actualizar o migrar a Angular 16?, ¿quieres saber qué trae esta súper versión de Angular?

En este artículo te digo que la versión que más ilusión me ha hecho de Angular hasta ahora sin ninguna duda es la 17 💞


Vamos al lío 🧵

Bienvenido SSR a Angular 😍

Hasta ahora Angular utilizaba Webpack para compilar, sólo Webpack.


En la versión 16 ya podíamos usar el compilador browser-esbuild que utilizaba VITEJS lo que nos otrogaba un mayor rendimiento en nuestras aplicaciones de Angular pero... no tenía server side rendering (SSR) 😠


Browser-esbuild es compatible con Webpack.


Antes de entrar a fondo con el SSR necesito que comprendas los compiladores que utiliza Angular.

Compiladores en Angular 17

En la versión 17 tendremos dos compiladores nuevos, el dev-server y el application


En realidad el dev-server es un browser-esbuild tuneado que tiene retrocompatibilidad con los compilares anteriores.


El nuevo compilador application que SÍ TIENE SSR 🤯💣


El compilador application será el que utilice Angular 17 por defecto.


Antes de explicarte cómo configurar tu aplicación para que tenga SSR te tengo que explicar cómo configurar en tu aplicación Angular que compile con application, si no, no será posible.


RECOMENDACIÓN: si vas a crear un proyecto desde cero y quieres que tenga SSR utiliza el comando ng new --ssr y Angular configurará todo por ti 😍

¿Cómo eligo el compilador en Angular 17?

Es estúpidante sencillo:

  1. Abres tu fichero angular.json
  2. Buscas el campo architect
  3. Dentro buscas el campo build
  4. Y en el campo builder escribes cuál quieres

    • browser
    • browser-esbuild
    • application
builder browser en angular.json con angular 17

Para elegir el compilador application además tienes que cambiar el campo main de options por un campo que se llamará browser

añadiendo builder application en angular.json con angular 17

¿Cómo configuro el SSR en Angular 17?

No me voy a entretener en explicarte cómo se hacía antes, es muy tarde.

Te voy a contar cómo se hace a partir de ahora con Angular 17 que me resulta increíblemente rápido.


Lo único que tienes que hacer es añadir un nuevo campo que se llamará ssr a las options del build de tu angular.json y cuyo valor será el siguiente objeto "entry":"server.ts" 🤯


Sencillamente fantástico

añadiendo ssr en angular.json con angular 17

Listo, ya tendrías SSR 🔥

Nueva sintaxis en Angular 17 para el if else

La sintaxis de Angular es una de las cosillas que no me terminaba de gustar.


De hecho, creo que es lo que al principio más inclina la curva de aprendizaje de Angular, que su sintaxis no es muy intuitiva.


Por ejemplo, para hacer un simple if en el template tenías que saber qué era una directiva estructural, en este caso el *ngIf, después cómo referenciar a una plantilla (un ng-template usando el #)... uf... es de locos la cantidad de cosas que tienes que saber para hacer un simple if else en el HTML


De la forma tradicional sería:

<div *ngIf="producto; else no_hay_producto">Renderizo el producto</div>

<ng-template #no_hay_producto>Renderizo que no hay producto</ng-template>
      

Ahora Angular apuesta por una forma más declarativa.


Con la nueva sintáxis 😍

@if (producto) 
  { Renderizo el producto }
  @else 
  { Renderizo que no hay producto }
      

Para el *ngFor y el *ngSwitch era otro drama.

Nueva sintaxis en Angular 17 para el switch

De la forma tradicional sería:

<div [ngSwitch]="mostrar_imagen_producto">
  <div *ngSwitchCase="1">Imagen 1</div>
  <div *ngSwitchCase="2">Imagen 2</div>
  <div *ngSwitchDefault>Imagen default</div>
      

Con la nueva sintáxis 😍

@switch (mostrar_imagen_producto) { 
  @case (1) {Imagen 1}
  @case (2) {Imagen 2}
  @default {Imagen default}
  }
      

Nueva sintaxis en Angular 17 para el for

Con la nueva sintáxis 😍

@for (producto of productos; track producto.id) {
  <div>{ { producto.nombre } }</div>
} @empty } 👈// si el array está vacío
  La lista de productos está vacía
}
      

Lo más importante es cómo se declara ahora el trackBy.

De hecho, lo que más destacaría es que ahora es obligatorio declararlo, porque antes no, y si no lo hacías tenía un impacto en el rendimiento de la aplicación muy serio.


El motivo es que el trackBy es como la key de una tabla de hash, identificada de forma única y sin error a cada item.


Si no declaramos el trackBy y por ejemplo, eliminar un item, tendríamos que volver a recorrer todo el array para ver qué item se ha eliminado.

Creo que se entiende.


Puedes usar el valor que se usaba por defecto track $index


De forma que la nueva sintaxis quedaría:

        @for (item of items; track $index) {
          
}

Vistas diferidas o defer views o vista aplazable (lazy loading) en Angular 17

Imagina que quieres renderizar dinámicamente y condicionalmente un componente, por ejemplo, una lista de productos.

Pero además, hacerlo sólo cuando el scroll de la página llegue a la lista de productos usando el interceptor observer o lo que viene siendo lo mismo, una carga de componentes diferida (de ahí el término defer) o lazy loading.

Ahora se puede... y muy simple 💃


Además, mientras se está cargando la lista que se renderize un loading y si falla la petición al servidor que cargue un template de error 😩


Me da pereza escribir cómo se hacía hasta ahora, así que directamente te digo cómo se hace a partir la versión 17

<div #mi_componente> 
  @defer (on viewport(mi_componente); prefetch on idle) { //lazy loading a nivel de componente
    <lista_productos/>
  } <loading {
    mi_loading
  } <error {
    Falló la carga de la lista 
  }
</div>
        

Con esto se consigue que los componentes se carguen de forma granular, es decir, que sólo se cargarán cuando se muestren en pantalla.


Me suena de algo... QuickJS? 🤷‍♀️


En la versión 17 de Angular conseguimos hacer una carga diferida de componentes.

Hasta ahora, sólo la podíamos hacer de módulos.

Si no sabes lo que es el lazy loading de los módulos de Angular te dejo un artículo en el que te digo qué es y cómo se hace.

Imagen del artículo

Lazy loading en Angular

En este artículo te cuento cómo realizar lazy load o carga asíncrona, diferida o perezosa con Angular


Defer triggers en Angular 17

Las palabras reservadas on idle en el ejemplo anterior, son un trigger o disparador y con él le estamos indicando que queremos que se cargue el componente cuando el navegador no está haciendo ningún trabajo intensivo.

Con componente me refiero a cualquier elemento HTML o componente personalizado.


Puedes usar dos tipos de triggers para indicar cuando cargar un componente aplazable.

Con when y con on


Usaremos when con alguna condición, es decir, con algo que devuelva true o false.

Es similar a lo que utilizaríamos para un @if

@defer (when mi_condicion){
  <app-mi-componente />
  }
      

Por otro lado usaremos on con triggers como:

  • on idle; el componente se cargará cuando el navegador no esté haciendo ningún trabajo intensivo, es decir, esté inactivo (idle)
  • on viewport; el componente se renderizará cuando entre en el viewport, es decir, cuando sea visible por el usuario
  • on immediate; el componente se renderizará sin bloquear el navegador tan pronto como el navegador finalize de renderizar la página
  • on timer(ms); el renderizado comenzará después de los milisegundos que especifiques
  • on interaction; se dispara cuando el usuario interactúa con un elemento específico haciendo clic o keydown
  • on hover; se dispara cuando el cursor del ratón para sobre el elemento

Te dejo aquí enlace a la documentación oficial

¿Cómo migrar automáticamente a la nueva sintaxis de Angular 17?

Sí, el equipo de Angular ha pensado en todo.


En un mismo template puedes usar las directivas estructurales de Angular (*ngIf...) combinadas con la nueva sintaxis de Angular 17, pero te perderás las mejoras de rendimiento que implica el hacerlo todo con la nueva sintaxis.


Si quieres migrar a la nueva sintaxis automáticamente usa el schematicng g @angular/core:control-flow

Nueva web y documentación para Angular 17

La nueva web de Angular está chulísima.


Y no me refiero sólo a la estética, que también, si no sobre todo a que tiene un playground para hacer pruebas agilizando mucho el trabajo.

¿Cómo sabemos con qué versión de Angular estamos trabajando?

Podemos ver qué versión de Angular es con la que estamos trabajando de las varias formas 📃

Con el package.json

Abriendo el package.json, en la sección de las dependencias encontraremos el Angular Core y ahí podremos ver la versión de Angular

  "@angular/animations": "~16.0.0",
  "@angular/cdk": "^16.0.3",
  "@angular/common": "~16.0.0",
  "@angular/compiler": "~16.0.0",
  "@angular/core": "~16.0.0"

Ejecutando la aplicación

Ejecutando la aplicación y en con las herramientas de depuración del navegador, podremos ver en la inspección de elementos el ng-version

<app-root _nghost-serverapp-c136="" ng-version="16.0.0">...

Con el CLI

Ejecutando el comando ng version en la consola en el directorio de trabajo, ello te facilitará toda la información de tu proyecto de Angular

¿Cómo actualizar/migrar a Angular 17?

Voy a seguir las recomendaciones del equipo de Angular en su documentación


Para actualizar mi aplicación de Angular 16 a Angular 17 que incluye Angular Material seguiré los siguiente pasos:

  1. ng update @angular/core @angular/cli
  2. ng update @angular/material

Actualizar Angular CLI globalmente

Te recomiendo actualizar tu Angular CLI de manera global y así, cada vez que crees un proyecto nuevo lo harás con la última versión de Angular

    Para actualizar Angular CLI de forma global sigue los siguientes pasos:
  1. Desinstala Angular CLI

    npm uninstall -g @angular/cli
  2. Limpia el cache de npm, y así cuando instalemos la nueva versión de Angular CLI nos aseguramos de que está limpia

    npm cache clean --force
  3. Instala la última versión estable de Angular CLI

    npm i -g @angular/cli
  4. Comprueba que se ha instalado la última versión

    ng version

Puedes encontrar más información acerca de Angular CLI en su página oficial de npm

Posibles errores

Package '@angular/core' is not a dependency

Es posible que no tengas la carpeta node_modules debido a que has clonado el repositorio. Para solventarlo instala las depencias de proyecto con:

npm install

Cuando todo falla

Cuando todo falla, el procedimiento que uso es:

  1. Crear un nuevo proyecto con el Angular CLI actualizado a la versión de Angular que quiero
  2. Eliminar la carpeta node_modules
  3. Eliminar el fichero package-lock.json
  4. Modificar las dependencias de mi proyecto de Angular que quiero migrar copiando las versiones del proyecto creado nuevo
  5. Instalar dependencias con npm install

No es lo más rápido, pero funciona.


Las depencias que te recomiendo para Angular 17 son:

  "dependencies": {
    "@angular/animations": "^17.1.0",
    "@angular/cdk": "^17.1.5",
    "@angular/common": "^17.1.0",
    "@angular/compiler": "^17.1.0",
    "@angular/core": "^17.1.0",
    "@angular/forms": "^17.1.0",
    "@angular/material": "^17.1.5",
    "@angular/platform-browser": "^17.1.0",
    "@angular/platform-browser-dynamic": "^17.1.0",
    "@angular/router": "^17.1.0",
    "rxjs": "~7.8.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.13.0"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^17.1.4",
    "@angular/cli": "~17.1.4",
    "@angular/compiler-cli": "^17.1.0",
    "@types/jasmine": "~4.3.0",
    "jasmine-core": "~4.6.0",
    "karma": "~6.4.0",
    "karma-chrome-launcher": "~3.2.0",
    "karma-coverage": "~2.2.0",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "~2.1.0",
    "typescript": "~5.1.3"
  }
              

Hasta luego 🖖