Благодаря RFC о строго типизированных реактивных формах закрыта проблема на GitHub №1, а RFC автономных API представил упрощённый способ создания приложений Angular. Подробностями делимся к старту курса по Frontend-разработке.


Мы рады объявить о выпуске Angular v14! От типизированных форм и автономных компонентов до новых примитивов в Angular CDK (набор для разработки компонентов) — мы рады поделиться тем, как каждая функция делает Angular мощнее.

В стремлении к инклюзивному сообществу мы переименовали ветку по умолчанию в репозиториях, в организации Angular на main.

Этот выпуск содержит множество функций и исправлений ошибок от сообщества, с добавления строгой типизации маршрутизатора до более строгих сообщений об ошибках. Радостно рассказать, как RFC и сообщество продолжают улучшать Angular для разработчиков!

Упрощение через автономные компоненты

Автономные компоненты Angular упрощают разработку приложений Angular за счёт уменьшения потребности в NgModules. В Angular 14 автономные компоненты находятся в режиме предварительной версии для разработки. Они готовы к применению для изучения и разработки, но API нестабильны, они могут измениться за пределами типичной модели обратной совместимости.

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common'; // includes NgIf and TitleCasePipe
import { bootstrapApplication } from '@angular/platform-browser';

import { MatCardModule } from '@angular/material/card';
import { ImageComponent } from './app/image.component';
import { HighlightDirective } from './app/highlight.directive';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    ImageComponent, HighlightDirective, // import standalone Components, Directives and Pipes
    CommonModule, MatCardModule // and NgModules
  ],
  template: `
    <mat-card *ngIf="url">
      <app-image-component [url]="url"></app-image-component>
      <h2 app-highlight>{{name | titlecase}}</h2>
    </mat-card>
  `
})
export class ExampleStandaloneComponent {
  name = "emma";
  url = "www.emma.org/image";
}

// Bootstrap a new Angular application using our `ExampleStandaloneComponent` as a root component.
bootstrapApplication(ExampleStandaloneComponent);

С автономными компонентами, директивами и каналами флаг standalone: true позволяет добавлять imports прямо в @Component() без @NgModule().

Изучите новое демо-приложение Stackblitz, чтобы больше узнать о разработке с использованием автономных компонентов.

В предварительной версии для разработчиков мы хотим использовать открытый исходный код, чтобы гарантировать, что автономная версия полностью готова к выпуску в качестве стабильного API. Добавьте свой первый автономный компонент с помощью ng generate component <name> --standalone, перейдите в наш репозиторий GitHub, чтобы оставить отзыв, когда начнёте изучение.

В ближайшие месяцы мы продолжим создавать схемы (например, ng new <app-name> --standalone), а также документировать варианты применения и процесс обучения для оптимизированной ментальной модели. Имейте в виду, что предварительная версия для разработчиков может измениться: мы продолжаем работу над проектами.

Узнать больше о дизайн-решениях в основе текущей реализации можно в двух RFC и общедоступном обзоре дизайна. Не забудьте подписаться на нас на Medium и в Twitter, чтобы быть в курсе обновлений автономных API.

Типизированные формы

Angular 14 закрывает главную проблему Angular на GitHub — строгую типизацию для пакета Reactive Forms.

Типизированные формы представляют автодополнение для значений и элементов управления
Типизированные формы представляют автодополнение для значений и элементов управления
Окно VSCode для группы форм Angular v14. Редактор поддерживает ввод для FormGroup и FormControls. Код здесь: https://gist.github.com/twerske/c06a9dcea9eee1f881d5d08551c8e873
Окно VSCode для группы форм Angular v14. Редактор поддерживает ввод для FormGroup и FormControls. Код здесь: https://gist.github.com/twerske/c06a9dcea9eee1f881d5d08551c8e873

Типизированные формы обеспечивают безопасность типов значений внутри элементов управления, групп и массивов форм на всей поверхности API. Это позволяет создавать более безопасные формы, особенно для глубоко вложенных сложных случаев.

const cat = new FormGroup({
   name: new FormGroup({
      first: new FormControl('Barb'),
      last: new FormControl('Smith'),
   }),
   lives: new FormControl(9),
});

// Type-checking for forms values!
// TS Error: Property 'substring' does not exist on type 'number'.
let remainingLives = cat.value.lives.substring(1);

// Optional and required controls are enforced!
// TS Error: No overload matches this call.
cat.removeControl('lives');

// FormGroups are aware of their child controls.
// name.middle is never on cat
let catMiddleName = cat.get('name.middle');

Эта функция — результат запроса общества и обзора дизайна на основе предварительного прототипирования, работы и тестирования от участников сообщества Angular, в том числе Сону Капур, Нетанель Базель и Седрика Эксбрайата.

Схемы обновления позволяют постепенно переходить к типизированным формам, поэтому добавлять типизацию с полной обратной совместимостью можно к существующим формам.

Команда ng update заменит все классы форм нетипизированными версиями (FormGroup -> UntypedFormGroup). Затем включать типы можно в своём темпе (например, UntypedFormGroup -> FormGroup).

// v13 untyped form
const cat = new FormGroup({
   name: new FormGroup(
      first: new FormControl('Barb'),
      last: new FormControl('Smith'),
   ),
   lives: new FormControl(9)
});

// v14 untyped form after running `ng update`
const cat = new UntypedFormGroup({
   name: new UntypedFormGroup(
      first: new UntypedFormControl('Barb'),
      last: new UntypedFormControl('Smith'),
   ),
   lives: new UntypedFormControl(9)
});

Чтобы воспользоваться преимуществами новой поддержки типизации, мы рекомендуем искать экземпляры нетипизированных элементов управления и по возможности переходить на новую поверхность API типизированных форм.

// v14 partial typed form, migrating `UntypedFormGroup` -> `FormGroup`
const cat = new FormGroup({
   name: new FormGroup(
      first: new UntypedFormControl('Barb'),
      last: new UntypedFormControl('Smith'),
   ),
   lives: new UntypedFormControl(9)
});

В новых приложениях также рекомендуется использовать классы Form*, если только класс не лишён типа преднамеренно. Пример — FormArray, который содержит и числа, и строки). Узнайте больше в документации.

Встроенные лучшие практики

Angular 14 предоставляет встроенные функции, позволяющие разрабатывать приложения высокого качества, от маршрутизации до вашего редактора кода, начиная с новых руководств angular.io по обнаружению изменений.

Соответствие контента страниц заголовкам

Лучшая практика — гарантировать, что заголовки страниц приложения однозначно передают содержимое. v13.2 упрощает представление этой гарантии с помощью нового свойства в Angular Router — [Route.title] . Добавление title теперь не требует дополнительного импорта и строго типизировано благодаря замечательному вкладу Марко Станимировича.

const routes: Routes = [{
  path: 'home',
  component: HomeComponent
  title: 'My App - Home'  // <-- Page title
}, {
  path: 'about',
  component: AboutComponent,
  title: 'My App - About Me'  // <-- Page title
}];

Настроить сложную логику заголовков можно предоставлением пользовательской TitleStrategy.

const routes: Routes = [{
  path: 'home',
  component: HomeComponent
}, {
  path: 'about',
  component: AboutComponent,
  title: 'About Me'  // <-- Page title
}];

@Injectable()
export class TemplatePageTitleStrategy extends TitleStrategy {
  override updateTitle(routerState: RouterStateSnapshot) {
    const title = this.buildTitle(routerState);
    if (title !== undefined) {
      document.title = `My App - ${title}`;
    } else {
      document.title = `My App - Home`;
  };
};

@NgModule({
  …
  providers: [{provide: TitleStrategy,  useClass: TemplatePageTitleStrategy}]
})
class MainModule {}

В этих примерах при переходе к "/about" заголовок документа устанавливается на «My App — About Me», а при переходе к "/home" — на «My App — Home».

Узнать об этой функции больше можно на семинаре Google I/O 2022 по созданию специальных возможностей с помощью Angular.

Узнайте, как разрабатывать на Angular на семинаре Google I/O 2022

Расширенные диагностики разработки

Новая расширенная диагностика предоставляет расширяемую структуру, которая лучше информирует о шаблонах и о возможности их улучшения. Эта диагностика выявляет ошибки во время запуска и выдаёт точные и действенные предложения. Мы в восторге от гибкой среды, которую она предоставляет разработчикам для добавления диагностик в будущем.

Расширенная диагностика помогает выявить распространённые ошибки Angular перед запуском
Расширенная диагностика помогает выявить распространённые ошибки Angular перед запуском

В версии 13.2 мы включили встроенную расширенную диагностику, чтобы помочь разработчикам выявить две самые распространённые ошибки шаблонов.

Банан в ящике

Перестановка квадратных и круглых скобок — в двустороннем связывании, ([]) вместо [()] — распространённая ошибка. () выглядит как банан, а [] — как ящик, эту ошибку мы назвали «банан в ящике», так как банан должен идти в ящике.

Хотя этот синтаксис допустим технически, CLI может распознать, что этот синтаксис редко соответствует намерениям разработчиков. Подробное сообщение об этой ошибке и руководство по её устранению в CLI и редакторе кода мы представили в версии v13.2.

Warning: src/app/app.component.ts:7:25 - warning NG8101: In the two-way binding syntax the parentheses should be inside the brackets, ex. '[(fruit)]="favoriteFruit"'.
        Find more at https://angular.io/guide/two-way-binding
7     <app-favorite-fruit ([fruit])="favoriteFruit"></app-favorite-fruit>
                          ~~~~~~~~~~~~~~~~~~~~~~~~~

Оператор объединения null и необнуляемое значение

Расширенная диагностика выявляет ошибки бесполезных операторов объединения null (??) в шаблонах Angular. В частности, эта ошибка возникает, когда ввод не является «обнуляемым»: его тип не включает null или undefined.

Расширенная диагностика отображается в виде предупреждений во время ng build, ng serve и в режиме реального времени с помощью языковой службы Angular. Диагностика настраивается в tsconfig.json, где вы можете указать, должна ли диагностика быть предупреждением, ошибкой или подавлением.

{
  "angularCompilerOptions": {
    "extendedDiagnostics": {
      // The categories to use for specific diagnostics.
      "checks": {
        // Maps check name to its category.
        "invalidBananaInBox": "error"
        "nullishCoalescingNotNullable": "warning"
      },
      // The category to use for any diagnostics not listed in `checks` above.
      "defaultCategory": "suppress"
    },
    ...
  },
  ...
}

Узнайте больше о расширенной диагностике в нашей документации и в посте о расширенной диагностике.

Рефакторинг сообщений об ошибках

По мере того, как мы продолжаем наши руководства по отладке Angular, вклад Рамеша Тиручельвама добавляет новые коды ошибок во время выполнения. Надёжные коды ошибок упрощают поиск информации об отладке.

Это позволяет оптимизатору сборки удалять сообщения об ошибках (длинные строки) из продакшн-пакетов, сохраняя при этом коды ошибок.


@Component({...})
class MyComponent {}

@Directive({...})
class MyDirective extends MyComponent {}  // throws an error at runtime

// Before v14 the error is a string:
> Directives cannot inherit Components. Directive MyDirective is attempting to extend component MyComponent.

// Since v14 the error code makes this tree-shakeable:
> NG0903: Directives cannot inherit Components. Directive MyDirective is attempting to extend component MyComponent.

// v14 production bundles preserve the error code, tree-shaking strings and making the bundle XX smaller:
> NG0903

Чтобы отладить производственную ошибку, мы рекомендуем обратиться к нашим справочным руководствам и воспроизвести ошибку в среде разработки, чтобы просмотреть полную строку. Мы продолжим поэтапный рефакторинг существующих ошибок, чтобы использовать этот новый формат в будущих релизах.

Больше встроенных улучшений

Angular v14 включает поддержку последней версии TypeScript 4.7 и теперь по умолчанию ориентирован на ES2020, что позволяет CLI поставлять меньше кода без понижения уровня логирования.

Есть ещё три заслуживающих внимания функции:

Привязка к защищённым членам компонента

В версии 14 вы теперь можете привязываться к защищённым элементам компонентов непосредственно из своих шаблонов благодаря вкладу Зака Эллиотта!

@Component({
  selector: 'my-component',
  template: '{{ message }}',  // Now compiles!
})
export class MyComponent {
  protected message: string = 'Hello world';
}

Это даёт больше контроля над общедоступной поверхностью API повторно используемых компонентов.

Optional injectors in Embedded Views

v14 добавляет поддержку передачи дополнительного инжектора при создании встроенного представления через ViewContainerRef.createEmbeddedView и TemplateRef.createEmbeddedView. Инжектор позволяет настроить поведение внедрения зависимостей в конкретном шаблоне.

Это позволяет использовать более чистые API для создания повторно используемых компонентов и примитивов компонентов в Angular CDK.

viewContainer.createEmbeddedView(templateRef, context, {
  injector: injector,
})

NgModel OnPush

И, наконец, вклад Артура Андросовича закрывает главную проблему и гарантирует, что изменения NgModel отражаются в пользовательском интерфейсе для компонентов OnPush.

@Component({
  selector: 'my-component',
  template: `
    <child [ngModel]="value"></child>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
class MyComponent {}

Встроенные примитивы и инструментарий

Усовершенствования CDK и инструментальных средств предоставляют строительные блоки для более надёжной среды разработки, от примитивов меню CDK до автоматического завершения команд CLI.

Новые примитивы в Angular CDK

Component Dev Kit предоставляет полный набор инструментов для создания компонентов Angular. В версии 14 мы продвигаем Menu и Dialog к стабильным версиям!

Material Dialog теперь строится на CDK Dialog
Material Dialog теперь строится на CDK Dialog

Этот релиз содержит новые примитивы CDK, которые можно использовать для создания более доступных пользовательских компонентов на основе шаблонов проектирования меню и строк меню WAI-ARIA.

<ul cdkTargetMenuAim cdkMenuBar>
  <li cdkMenuItem    
      [cdkMenuTriggerFor]="file">
    File
  </li>
</ul>
<ng-template #file>
  <ul cdkMenu cdkTargetMenuAim>
    <li cdkMenuItem>Open</li>
  </ul>
</ng-template>

hasHarness и getHarnessOrNull в Component Test Harnesses

v14 содержит новые методы HarnessLoader, проверяющие присутствие harness и возвращающие его экземпляр, если он есть. Комплекты тестирования Harness по-прежнему предоставляют возможность написать хорошие, гибкие тесты.

const loader = TestbedHarnessEnvironment
    .loader(fixture);

const hasButton = await loader
    .hasHarness(MatButtonHarness)

const buttonHarnessOrNull = await loader
    .getHarnessOrNull(MatButtonHarness);

Улучшения Angular CLI

Стандартизированный анализ аргументов CLI означает большую согласованность во всем Angular CLI, и теперь каждый флаг прописывается в формате --lower-skewer-case. Мы удалили поддержку устаревших аргументов в верблюжьем регистре и добавили поддержку комбинированного применения алиасов. Запустите ng --help — команда разъяснит варианты.

ng completion

Ввод ng sevre вместо ng serve случается постоянно. Опечатки - одна из самых распространённых причин ошибок. Для решения этой проблемы в v14 появился новый ng completion, который вводит автозавершение в реальном времени с опережением ввода!

Чтобы все разработчики Angular знали об этом, в версии 14 CLI во время первого выполнения команды вам будет предложено отказаться от автозаполнения. Вы также можете вручную запустить ng completion, и CLI автоматически настроит его для вас.

Терминал с Angular CLI, выполняющим `ng generate component` и в каждом приглашении. Перед нажатием TAB и CLI вводятся Только первые несколько букв, команда завершается автоматически
Терминал с Angular CLI, выполняющим `ng generate component` и в каждом приглашении. Перед нажатием TAB и CLI вводятся Только первые несколько букв, команда завершается автоматически

ng completion — автодополнение в Angular CLI.

ng analytics

Команда CLI analytics позволяет управлять настройками аналитики и выводить аналитическую информацию. Более подробная информация чётко передаёт конфигурации аналитики и предоставляет нашей команде данные телеметрии для определения приоритетов проекта. Включение этой функции по-настоящему помогает!

ng analytics в Angular CLI
ng analytics в Angular CLI

ng cache

ng cache — способ управления и печати информации о кэше из командной строки. Вы можете включать, отключать или удалять с диска, а также распечатать статистику и информацию.

ng cache  в Angular CLI
ng cache в Angular CLI

Angular DevTools в Firefox доступны оффлайн

Расширение отладки Angular DevTools поддерживает автономное использование благодаря вкладу Keith Li. Расширение для Firefox вы найдёте в Аддонах для Firefox.

Firefox с запущенным расширением Angular DevTools.
Firefox с запущенным расширением Angular DevTools.

Экспериментальная система сборки ESM

v14 представляет экспериментальную систему сборки на основе esbuild для ng build, которая компилирует чистый вывод ESM. Обновите сборщик браузера в файле angular.json, чтобы попробовать это в своём приложении:

"builder": "@angular-devkit/build-angular:browser"

"builder": "@angular-devkit/build-angular:browser-esbuild"

Наша команда рада собрать отзывы о производительности вашего приложения, поскольку мы продолжаем добавить поддержку препроцессоров таблиц стилей, таких как Sass.

А что дальше?

Мы обновили публичный план развития, чтобы отразить статус текущих и будущих командных проектов и исследований.

Вы можете узнать больше о планах нашей команды на будущее в блоге Angular и в State of Angular от #GoogleIO. Спасибо всем замечательным разработчикам, внедряющим инновации и мотивирующим нас каждый день — мы в восторге от того, куда движется Angular! Зайдите на update.angular.io и напишите нам на @Angular о своём #ngUpdate!

А мы поможем прокачать ваши навыки или с самого начала освоить профессию, востребованную в любое время:

Выбрать другую востребованную профессию.

Комментарии (2)


  1. KhodeN
    13.06.2022 01:52
    +7

    Перевод очень корявый, машинный, как-будто. Вроде и понятно, но ухо режет.


  1. Alendorff
    14.06.2022 23:09
    +1

    Ну вышел и вышел.