Вийшов Angular 20: розбираємося, що нового
Команда Angular випустила
Нові експериментальні API в Angular
Щоб краще працювати з асинхронними даними, команда Angular ще у версії 19 додала resource API, а в Angular 20 розширила цю можливість — тепер з’явилися resource streaming та httpResource.
Приклад: завантаження користувача
const userId: Signal<string> = getUserId();
const userResource = resource({
params: () => ({ id: userId() }),
loader: ({ request, abortSignal }) => {
return fetch(`users/${request.id}`, { signal: abortSignal });
},
});
Цей код автоматично підвантажує користувача, коли змінюється userId.
Приклад: стрімінг даних через WebSocket
@Component({
template: `{{ dataStream.value() }}`
})
export class App {
dataStream = resource({
stream: () => {
return new Promise(resolve => {
const resourceResult = signal({ value: [] });
this.socket.onmessage = event => {
resourceResult.update(current => ({
value: [...current.value, event.data]
}));
};
resolve(resourceResult);
});
},
});
}
Цей приклад показує, як працювати з потоковими даними — наприклад, із WebSocket. Кожне нове повідомлення додається у список, а UI оновлюється автоматично.
Приклад: httpResource для HTTP-запитів
@Component({
template: `{{ userResource.value() | json }}`
})
class UserProfile {
userId = signal(1);
userResource = httpResource<User>(() =>
`https://example.com/v1/users/${this.userId()}`
);
}
Тут кожна зміна userId автоматично тригерить новий HTTP-запит. API повертає об’єкт з усім необхідним: value, isLoading, headers тощо.
Працює все на базі HttpClient, тому можна підключати інтерсептори:
bootstrapApplication(AppComponent, {
providers: [
provideHttpClient(
withInterceptors([loggingInterceptor, cachingInterceptor])
),
],
});
Zoneless
Angular 20 зробив великий крок до так званого zoneless-режиму, де зміни в UI відслідковуються без zone.js. Це простіше, швидше і чистіше.
Додано:
- Підтримку обробки глобальних помилок у Node.js (SSR):
unhandledRejection,uncaughtException. - Глобальні слухачі помилок у браузері через
provideBrowserGlobalErrorListeners/
Як підключити:
bootstrapApplication(AppComponent, {
providers: [
provideZonelessChangeDetection(),
provideBrowserGlobalErrorListeners(),
],
});
Не забудьте прибрати zone.js із angular.json, якщо переходите на zoneless.
Стабільна серверна підтримка
Angular 20 зробив стабільними дві важливі фічі:
Інкрементальна гідратація (incremental hydration)
Завантажується лише те, що потрібно, а не весь DOM одразу:
import {
provideClientHydration,
withIncrementalHydration,
} from '@angular/platform-browser';
provideClientHydration(withIncrementalHydration());
Рендеринг на рівні маршрутів
Тепер можна задавати, як рендерити окремі маршрути: на сервері (SSR), на клієнті (CSR) або заздалегідь (Prerender):
export const routeConfig: ServerRoute = [
{ path: '/login', mode: RenderMode.Server },
{ path: '/dashboard', mode: RenderMode.Client },
{
path: '/product/:id',
mode: RenderMode.Prerender,
async getPrerenderParams() {
const dataService = inject(ProductService);
const ids = await dataService.getIds(); // ["1", "2", "3"]
return ids.map(id => ({ id }));
}
}
];
Це дає змогу оптимізувати швидкість і UX кожного окремого маршруту.
Динамічне створення компонентів з директивами та байндингами
У версії 20 Angular нарешті дозволяє створювати компоненти динамічно — не просто з інпутами й аутпутами, а ще й з директивами та двосторонніми байндингами.
Приклад:
import { createComponent, signal, inputBinding, outputBinding, twoWayBinding } from '@angular/core';
const canClose = signal(false);
const title = signal('My dialog title');
createComponent(MyDialog, {
bindings: [
inputBinding('canClose', canClose),
outputBinding<Result>('onClose', result => console.log(result)),
twoWayBinding('title', title),
],
directives: [
FocusTrap,
{
type: HasColor,
bindings: [inputBinding('color', () => 'red')],
},
]
});
Простими словами: можна створити компонент на льоту, передати йому дані, додати потрібні директиви — і все це без зайвої мороки.
Шаблони стали ближчими до JavaScript
Тепер Angular підтримує нові вирази прямо в шаблонах:
- Ступінь:
{{ n ** 2 }} - Оператор in:
{{ name in person }}
Шаблонні рядки:
<div [class]="`layout col-${colWidth}`"></div>
Це робить шаблони зрозумілішими для тих, хто звик до звичайного JavaScript.
Краще діагностування помилок
Angular почав ловити типові помилки ще на етапі розробки:
- Використання
??у невідповідному контексті - Забутий імпорт структурних директив (
@if,@for) - І коли ви передаєте функцію
trackFnу@forне викликаючи її
@for (user of users; track trackFn) {
<!-- ... -->
}
Такого роду дрібниці тепер виявляються автоматично.
Покращена підтримка host bindings
Тепер можна вмикати перевірку типів для host у компонентах — просто додайте:
"angularCompilerOptions": {
"typeCheckHostBindings": true
}
У версії 21 це буде вмикатися автоматично.
Тестування з Vitest
Angular офіційно експериментує з Vitest — сучасною альтернативою Karma. Підтримує watch mode, швидше працює, і взагалі набагато приємніший у використанні.
Щоб спробувати:
npm i vitest jsdom --save-dev
У angular.json:
"test": {
"builder": "@angular/build:unit-test",
"options": {
"tsConfig": "tsconfig.spec.json",
"buildTarget": "::development",
"runner": "vitest"
}
}
А у тестах:
import { describe, beforeEach, it, expect } from 'vitest';
І все — можна запускати ng test.
Material: кнопки стали ще кращими
Angular Material оновився відповідно до Material 3:
- Зʼявилась тональна кнопка (tonal button) — виглядає сучасніше і краще вписується в дизайн.
- Назви компонентів стали послідовнішими.
- Зʼявився новий селектор
matIconButton— щоб чітко вказувати, що це кнопка з іконкою. - Обʼєднано MatButton і MatAnchor — більше не треба імпортувати їх окремо.
Більше контролю в MatDialog і Overlay
У MatDialog зʼявився параметр closePredicate, який дозволяє вказати умови, за яких діалог можна закривати. Нарешті!
У Overlay — нові API, що краще працюють з tree-shaking. Тобто, у фінальний бандл потрапляє тільки те, що реально використовується.
Плавні анімації — або їх повна відсутність
Angular тепер поважає системне налаштування prefers-reduced-motion, що важливо для людей з чутливістю до руху.
А для повного вимкнення анімацій (наприклад, у тестах) можна використати спеціальний
Angular та ШІ
У новій версії зʼявився файл llms.txt, який допомагає
Також відкрито розділ angular.dev/ai — тут гайди, приклади, best practices для інтеграції GenAI, Genkit, Vertex AI тощо.
Кінець епохи *ngIf і друзів
Все. Крапка. *ngIf, *ngFor, *ngSwitch офіційно застарілі.
Angular ще у v17 представив новий синтаксис:
@if,@for,@switch- Пишеться як у JavaScript
- Не потребує імпорту директив
- Працює швидше
- Краще типізується
Щоб перейти на новий стиль, просто виконайте:
ng generate @angular/core:control-flow
Ця команда автоматично замінить старі конструкції у шаблонах.
І наостанок — Angular отримає власного маскота 🐟
Так, тепер у Angular буде талісман. Від «щита з очима» до симпатичної рибки-ліхтарика — команда розглядає різні варіанти. Можна долучитись до обговорення: запропонувати ідею, проголосувати чи навіть придумати ім’я.



Як думаєте, який маскот ідеально підійшов би Angular? Кидайте фото в коментарі 🙃
9 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів