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 — это мощное обновление с отличной обратной совместимостью.