23 sty 2025
6 min

Angular 19.1 – Co nowego?

Choć minęło niewiele czasu od wydania pełnej wersji Angular 19.0, już teraz możemy delektować się nową dawką usprawnień i smaczków w wersji 19.1. Co takiego zaoferowali nam twórcy? Zerknijmy wspólnie na kilka nowości.

Wsparcie dla TypeScript 5.7

Angular 19.1 jest w pełni kompatybilny z najnowszą wersją TypeScript 5.7.3, wydaną zaledwie kilka dni wcześniej. Mamy więc do dyspozycji cały pakiet aktualnych funkcji do wykorzystania.

Główne nowości w TypeScript 5.7:

  • Poprawione raportowanie błędów: TypeScript 5.7 wprowadził  ulepszone mechanizmy raportowania błędów, umożliwiając wykrywanie niezainicjowanych zmiennych
  • Wsparcie dla ES2024: Dodano obsługę nowych metod, takich jak Object.groupBy, co pozwala na bardziej zwięzłe i czytelne operacje na obiektach. 
  • Optymalizacje kompilatora: Wprowadzono różne usprawnienia w kompilatorze, które przyspieszają proces kompilacji i poprawiają ogólną wydajność.

Listę wszystkich mian możecie zobaczy tutaj: https://devblogs.microsoft.com/typescript/announcing-typescript-5-7/

Wizualna reprezentacja routera w Devtools

Od teraz Devtoolsy Angulara wzbogacone są o graficzne przedstawienie routingu aplikacji. Dzięki temu będziemy mogli zobaczyć w postaci grafu poszczególne ścieżki, które zostały już załadowane. 

Co więcej, możliwa jest także wizualizacja sygnałów. Jednak na ten moment ich śledzenie w takim wydaniu jest możliwe tylko poprzez prywatną funkcję ɵgetSignalGraph(). W przyszłości ma zostać wyeksponowana w devtoolsach w formie interaktywnego grafu pokazującego sygnały i ich zależności.

Aby otworzyć graf routingu, otwórz Devtoolsy Angulara, a następnie ustawienia i wybierz opcję ‘Enable Router Graph

Po prawej stronie pokaże Ci się nowa zakładka ‘Router Tree’.

Automatyczne usuwanie nieużywanych importów standalone

Dotychczas otrzymywaliśmy ostrzeżenia o importach komponentów i dyrektyw standalone które nie były używane. Od wersji 19.1 Angulara będą one automatycznie usuwane przy pomocy polecenia:

ng generate @angular/core:cleanup-unused-imports.

Nowe możliwości NgComponentOutlet

NgComponentOutlet to dyrektywa w Angularze, która umożliwia dynamiczne ładowanie komponentów w określonym miejscu w aplikacji. W poprzednich wersjach korzystanie z niej ograniczało się jedynie do pliku .ts. Aż do wersji Angular 19.1.

Przed tą aktualizacją, aby dynamicznie załadować komponent:

  • Musieliśmy używać API Angulara w pliku TypeScript, np. ComponentFactoryResolver, aby tworzyć instancje komponentów.
  • Było to bardziej złożone, ponieważ wymagało kodu TypeScript do zarządzania tworzeniem i wstrzykiwaniem komponentów.

Przykład wcześniejszego podejścia:

import { Component, ComponentFactoryResolver, ViewChild, ViewContainerRef } from '@angular/core';

@Component({
  selector: 'app-root',
  template: '<ng-container #dynamicContainer></ng-container>',
})
export class AppComponent {
  @ViewChild('dynamicContainer', { read: ViewContainerRef }) container!: ViewContainerRef;

  constructor(private resolver: ComponentFactoryResolver) {}

  loadComponent(component: any) {
    const factory = this.resolver.resolveComponentFactory(component);
    this.container.clear();
    this.container.createComponent(factory);
  }
}

W najnowszej wersji Angulara możemy dynamicznie ładować komponenty bezpośrednio w pliku HTML za pomocą NgComponentOutlet. Nie musimy już tworzyć instancji komponentów w kodzie TypeScript. Spójrzmy na przykład.

<ng-container 
  *ngComponentOutlet="dynamicComponent" 
  #outlet="ngComponentOutlet">
</ng-container>
  • *ngComponentOutlet=”dynamicComponent”:
    Angular wczytuje komponent określony przez zmienną dynamicComponent. Ta zmienna może być klasą komponentu przekazaną z pliku TypeScript.
  • #outlet=”ngComponentOutlet”:
    Tworzony jest lokalny kontekst (#outlet), który umożliwia interakcję z załadowanym komponentem (np. dostęp do instancji komponentu i jego API).

Zaś w pliku .ts mamy taki kod:

import { Component } from '@angular/core';
import { MyDynamicComponent } from './my-dynamic.component';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent {
  dynamicComponent = MyDynamicComponent; // Przypisanie klasy komponentu
}

To znacznie uprościło sposób dynamicznego ładowania komponentów, eliminując potrzebę tworzenia instancji komponentów w kodzie TypeScript i dodając większą elastyczność w tworzeniu dynamicznych komponentów.

Dyrektywa ta zyskała także nową właściwość – componentInstance. Dzięki niej mamy dostęp do instancji komponentu utworzonego przez tę dyrektywę.

Dzięki componentInstance możesz:

  • Uzyskać dostęp do metod i właściwości komponentu.
  • Zaktualizować dane lub przekazać nowe wartości do komponentu po jego załadowaniu.
  • Wykonać operacje na załadowanym komponencie, co wcześniej było trudniejsze, ponieważ NgComponentOutlet nie oferował bezpośredniego dostępu do instancji.

subPath w aplikacjach wielojęzycznych

W kontekście aplikacji wielojęzycznych Angular 19.1 wprowadził ciekawą opcję subPath, która jest rozszerzeniem funkcji baseHref. subPath automatycznie definiuje segmenty URL dla różnych języków (np. /pl, /en) oraz porządkuje w strukturze folderów wygenerowane pliki obsługujące dany język.

Dla większego kontekstu porównajmy oba rozwiązania

baseHref subPath
Musimy budować aplikację osobno dla każdego języka, np.

  • dla /pl/: ng build –configuration=pl
  • dla /en/: ng build –configuration=en

Efekt: oddzielne zestawy plików dla każdego języka. Jeśli masz więcej języków, liczba kompilacji rośnie.

Aplikacja jest budowana tylko raz z jednym ustawieniem baseHref (np. /). Wielojęzyczność jest obsługiwana przez router Angulara, który analizuje subścieżki URL (np. /pl, /en) i ładuje odpowiednie zasoby.

Efekt: proces budowania jest szybszy i bardziej efektywny, ponieważ generujemy tylko jedną wersję aplikacji.

Dla każdego języka musimy umieścić osobne pliki na serwerze w odpowiednich katalogach:

  • /pl/index.html
  • /en/index.html

Efekt: Wymaga to dodatkowej konfiguracji serwera i większej ilości miejsca, ponieważ pliki są powielane.

Wszystkie pliki aplikacji są wspólne i znajdują się w jednym miejscu. Serwer obsługuje różne języki poprzez analizę URL (np. /pl, /en) i przekierowuje na jeden index.html.

Efekt: Jest to prostsze w konfiguracji i zajmuje mniej miejsca na serwerze.

URL jest bardziej statyczny, np. 

  • /products
  • /en/products. 

Jeśli nie stosujemy dodatkowych mechanizmów, aplikacja może nie zawsze wskazywać język w URL, co utrudnia SEO.

Efekt: Możemy uzyskać /pl/ lub /en/, ale tylko w wyniku budowania różnych wersji aplikacji.

Każdy język jest wyraźnie widoczny w URL, np. 

  • /pl/products 
  • /en/products.

Efekt: Jest to korzystne dla SEO, ponieważ wyszukiwarki widzą odrębne strony dla każdego języka.

Możemy potrzebować dodatkowej logiki podczas budowania, np. translacje ładowane dla konkretnego języka w zależności od konfiguracji.

Efekt: Zmiana języka w uruchomionej aplikacji może wymagać przeładowania strony, ponieważ baseHref zmienia całą bazową ścieżkę aplikacji.

Angular Router pozwala na dynamiczną obsługę języków. Translacje są ładowane na podstawie subścieżki URL, co upraszcza kod.

Efekt:  Zmiana języka w aplikacji (np. z /pl na /en) nie wymaga przeładowania strony.

Mówiąc krócej, kiedy używamy subPath, Angular automatycznie generuje podkatalogi i ustawia baseHref dla każdego języka, co wpływa korzystnie na działanie aplikacji i pracę programisty.

Poniżej możemy zobaczyć jak wygląda struktura plików i folderów oraz fragment kodu w pliku angular.json z wykorzystaniem subPath.

/dist/
  my-app/
    pl/ (<base href="/my-app/pl/">)
      index.html 
      main.js
      styles.css
    en/ (<base href="/my-app/en/">)
      index.html
      main.js
      styles.css
   "my-app": {
      "i18n": {
        "locales": {
          "pl": {
            "translation": "src/locale/file.pl.json",
            "subPath": "pl"
          },
          "en": {
            "translation": "src/locale/file.en.json",
            "subPath": "en"
          }
        }
      }
    }

SSR: Przekierowanie do preferowanego języka

Serwer teraz przekierowuje użytkowników do ich preferowanych języków na podstawie ustawień przeglądarki, wykorzystując nagłówek Accept-Language. Funkcja ta działa automatycznie bez dodatkowej konfiguracji.

HMR dla templatek

W wersji Angular 19.0 HMR (Hot Module Replacement) został domyślnie włączony dla plików CSS, zaś w wersji 19.1 także dla plików HTML. Oznacza to, że zmiana kodu w pliku będzie powodować odświeżenie tylko danej templatki, a nie całej aplikacji. Co za tym idzie – nie stracimy stanu aplikacji z powodu odświeżenia, oraz zaoszczędzimy czas unikając przebudowania strony.

Na oficjalnym kanale Angular na platformie YouTube możecie zobaczyć jak to wygląda w praktyce  https://youtube.com/shorts/1h0ViHgAOGY?si=W_evMrztW0x6oZBX

Uproszczone generowanie bibliotek

Jako że ng-packagr został zintegrowany jako builder do CLI(@angular/build:ng-packagr), chcąc wykonać polecenie ng generate library do stworzenia biblioteki, nie musimy mieć zainstalowanej paczki @angular-devkit/build-angular.

Podsumowanie

Angular 19.1 wprowadza szereg usprawnień, które poprawiają wygodę pracy z frameworkiem. Nowości obejmują m.in. lepsze wsparcie dla TypeScript 5.7, ulepszenia w Devtools, automatyczne usuwanie nieużywanych importów oraz nowe funkcje dla aplikacji wielojęzycznych. Dodatkowo, zoptymalizowano proces budowania aplikacji i bibliotek, wprowadzając funkcje takie jak HMR dla templatek oraz automatyczne przekierowanie do preferowanego języka.

Podziel się artykułem

Zapisz się na nasz newsletter

Dołącz do community Angular.love i bądź na bieżąco z trendami.