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.
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:
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.
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.
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.