Angular 20: Большое обновление для современного веба
- вторник, 3 июня 2025 г. в 00:00:04
Angular 20 — это мощное обновление, которое делает разработку веб-приложений быстрее, удобнее и современнее. Новые возможности шаблонов, стабильные сигналы, поддержка zoneless режима и интеграция с AI позволяют создавать высокопроизводительные приложения с минимальными усилиями. В этой статье разберём ключевые нововведения Angular 20 и покажем, как их использовать в ваших проектах.
Angular 20 приближается к полной совместимости шаблонов с синтаксисом TypeScript, делая их более выразительными и удобными. Среди новых возможностей:
Шаблонные строки — позволяют делать интерполяцию более читаемой:
<p>{{ `User id: ${userId()}` }}</p>
Меченые шаблонные строки: Позволяют кастомизировать обработку строк, например, для форматирования или безопасного вывода:
function highlight(strings: TemplateStringsArray, ...values: any[]): string {
return strings.reduce((result, str, i) => result + str + (values[i] || ''), '');
}
@Component({...})
class MyComponent {
user = { name: 'Алексей' };
highlightedName = highlight`Пользователь: ${this.user.name}`;
}
Оператор возведения в степень (**): Упрощает вычисления в шаблонах:
{{ 2 ** 3 }} <!-- Выведет 8 -->
Оператор in: Удобная проверка наличия свойства в объекте:
@if ('magicDamage' in attack) {
<p>{{ `Урон магией: ${attack.magicDamage}` }}</p>
}
Оператор void: Гарантирует отсутствие побочных эффектов в обработчиках событий:
@Component({...})
class MyComponent {
onClick(event: Event): void {
console.log('Клик обработан');
return void 0;
}
}
Теперь свойство redirectTo
может возвращать Promise
, Observable<string>
или UrlTree
. Это позволяет учитывать авторизацию или другие данные перед перенаправлением.
const routes: Routes = [
{
path: 'admin',
redirectTo: async () => {
const isAuthorized = await checkAuthorization();
return isAuthorized ? '/dashboard' : '/login';
}
}
];
Метод Router.getCurrentNavigation()?.abort()
позволяет отменить переход по маршруту, что особенно полезно при интеграции с Navigation API.
Теперь NgComponentOutlet
поддерживает:
ngComponentOutletInputs
— передача входных данных
ngComponentOutletContent
— проекция контента
ngComponentOutletInjector
— пользовательский инжектор
Это упрощает создание динамических компонентов и делает код чище.
Angular 20 позволяет указывать input/output-связи, двустороннюю привязку и директивы напрямую при создании компонентов через ViewContainerRef.createComponent
.
bindings: [
inputBinding('canClose', this.canClose),
outputBinding('close', value => console.log(value))
]
Если вы создаете инжектор вручную через Injector.create()
, теперь можно вызвать destroy()
для очистки.
const injector = Injector.create({ providers: [...] });
injector.destroy();
Теперь можно отправлять данные (например, аналитику) при закрытии страницы с опцией keepalive:
@Component({...})
class AnalyticsComponent {
constructor(private http: HttpClient) {}
sendAnalyticsOnClose() {
this.http.post('/analytics', { event: 'page_closed' }, { keepalive: true })
.subscribe();
}
}
Методы scrollToAnchor
и scrollToPosition
теперь принимают ScrollOptions
для более гибкой прокрутки.
Теперь Angular проверяет типы выражений в @HostBinding
, @HostListener
и метаданных host
. Это упрощает отладку и рефакторинг.
Angular 20 предупреждает о некорректном использовании ??
, &&
и ||
без скобок:
<!-- Ошибка: неясный приоритет -->
<div>{{ value ?? defaultValue && fallback }}</div>
<!-- Корректно -->
<div>{{ (value ?? defaultValue) && fallback }}</div>
В @for теперь выдаётся предупреждение, если вы забыли вызвать функцию track, что помогает поддерживать производительность:
<!-- Ошибка: track не вызван -->
@for (item of items; track trackByName) {}
<!-- Корректно -->
@for (item of items; track trackByName(item)) {}
Angular теперь предупреждает, если вы используете свою директиву (*myDirective
) без импорта.
Сигналы: API toSignal, toObservable, linkedSignal и effect теперь в статусе Stable. Это делает сигналы готовыми для продакшена.
Переименование afterRender: Хук переименован в afterEveryRender для большей ясности.
Zoneless Angular: API для зонелесс-детекции изменений перешёл в Developer Preview. Новый провайдер: provideZonelessChangeDetection. CLI теперь предлагает выбрать zoneless режим при создании проекта. Также доступен provideCheckNoChangesConfig для проверки готовности к переходу. На рабочих проектах лучше дождаться статуса Stable.
API PendingTasks
стабилизирован и позволяет отложить SSR-ответ до завершения указанных задач. Также в статус Developer Preview переведён оператор pendingUntilEvent
.
Node: ^20.11.1 || ^22.11.0 || ^24.0.0
TypeScript: >=5.8.0 <5.9.0
RxJS: ^6.5.3 || ^7.4.0
Поддержка Node 18 и TypeScript <5.8 прекращена.
Angular больше не добавляет ng-reflect-*
в DOM. Если ваши тесты на это полагаются — переключитесь на data-testid
или data-cy
.
Теперь вместо InjectFlags используется объект настроек:
inject(ElementRef, { optional: true, host: true, skipSelf: true });
Поддержка HammerJS снята и будет удалена в Angular 21. Рекомендуется использовать нативные API (например, PointerEvent) или библиотеки вроде interact.js для обработки жестов.
Angular 20 предоставляет инструменты и рекомендации для интеграции генеративного AI:
Genkit: Фреймворк для упрощения работы с AI-моделями.
Firebase AI Logic: Инструмент для создания серверной AI-логики на платформе Firebase.
Gemini API: API для создания чат-ботов, генерации изображений и персонализированного контента.
Новый файл llms.txt помогает большим языковым моделям (LLMs) генерировать актуальный Angular-код:
Angular 20 интегрируется с Chrome DevTools, предоставляя метрики производительности сигналов и AI-компонентов (например, время выполнения effect или задержки в SSR). Это упрощает отладку и оптимизацию.
Angular 20 делает серьёзный шаг вперёд: новые возможности в шаблонах, стабильные сигнальные API, удобство работы с динамическими компонентами и подготовка к zoneless-архитектуре.
Ожидаем в будущем Signal Forms и Selectorless Components, но уже сейчас Angular 20 — это мощное обновление с отличной обратной совместимостью.