- PVSM.RU - https://www.pvsm.ru -
Автор материала, перевод которого мы публикуем, предлагает поговорить об Angular 8. Здесь будут рассмотрены некоторые особенно горячие темы, поднятые на мероприятиях NgConf и Google I/O 2019. Поэтому, если вы интересуетесь Angular, но по каким-то причинам не видели докладов с этих мероприятий, полагаем, вам любопытно будет узнать о том, чего можно ждать от Angular 8.
Уверен, что вы сейчас, с нетерпением ожидая выхода Angular 8, испытываете те же чувства, что испытывал я после NgConf 2019. В докладе [2] Игоря Минара затронуто множество ожидаемых новшеств — от инструментов до технологий вроде дифференциальной загрузки и многих других замечательных вещей.
Обсудим то, как всё это может повлиять на ваши проекты. А именно, рассмотрим новые возможности и поговорим о том, приведёт ли их появление к признанию устаревшими существующих механизмов, или к тому, что новое окажется несовместимым со старым.
При применении технологии дифференциальной загрузки (differential loading), Angular, в процессе сборки проекта, может создать отдельный бандл для полифиллов (polyfills). Это зависит от файла browserlist
. Вот как это, в общих чертах, будет выглядеть.
Сверху — новый способ упаковки проектов (источник [2])
Использование этой возможности позволит уменьшить размеры бандлов.
Экономия благодаря применению дифференциальной загрузки (источник [2])
Как же это работает?
Angular будет собирать дополнительные файлы с полифиллами и они будут внедряться в код с помощью атрибутов nomodule [3]:
<body>
<pp-root></pp-root>
<script type="text/javascript" src="runtime.js"></script>
<script type="text/javascript" src="es2015-polyfills.js" nomodule></script>
<script type="text/javascript" src="polyfills.js"></script>
<script type="text/javascript" src="styles.js"></script>
<script type="text/javascript" src="vendor.js"></script>
<script type="text/javascript" src="main.js"></script>
</body>
Атрибут nomodule
, логический, предотвращает загрузку и выполнение скрипта в браузерах, поддерживающих ES6-модули. Такие браузеры игнорируют подобные скрипты. Старые браузеры загружают и выполняют их.
Теперь SVG файлы можно будет использовать в качестве шаблонов. До сих пор в качестве шаблонов можно было использовать встроенный или внешний HTML-код.
@Component({
selector: "app-icon",
templateUrl: "./icon.component.svg",
styleUrls: ["./icon.component.css"]
})
export class AppComponent {...}
Движок Ivy всё ещё находится в экспериментальной стадии. После выхода Angular 8 его можно испытать, воспользовавшись при создании нового приложения флагом --enable-ivy
. Ниже показан соответствующий код. Помните о том, что Ivy пока ещё не вполне готов (он ещё находится в статусе «opt-in preview»), и, как сказал Игорь Минар на NgConf 2019, при создании новых приложений всё ещё рекомендуется использовать движок View Engine.
Для того чтобы включить использование Ivy в существующем проекте, нужно в файле tsconfig.app.json
установить в true
параметр enableIvyoption
в angularCompilerOptions
:
"angularCompilerOptions": {"enableIvy": true}
Можно и создать новое приложение, в котором будет использоваться Ivy:
$ ng new my-app --enable-ivy
Ivy предлагает следующие полезные возможности, появление трёх первых из которых ожидается в Angular 9:
Bazel — это очередной инструмент, переведённый Google в разряд опенсорсных. Игорь Минар говорит, что Bazel долгое время использовался для внутренних нужд компании, а теперь он доступен всем. Для того чтобы узнать подробности об этом сборщике проектов — загляните в документацию [5] и почитайте о том, как использовать Bazel с Angular [6].
Возможно, вы сейчас задаётесь вопросом о том, готов ли Bazel к практическому применению. Если кратко ответить на этот вопрос — то ещё не готов. Сейчас он пребывает в статусе «opt-in preview». Позволю себе процитировать Алекса Игла, который руководит в Google командой по разработке инструментов Angular: «Если вы уже входили в воды Bazel раньше, то не могли не заметить, что там было множество акул… Теперь с акулами уже справились, но вода всё ещё может оказаться холодной».
Bazel пока доводят до ума, ожидается, что его включат в @angular/cli
в версии 9.
Вот какие полезные возможности способен дать нам Bazel:
Добавить в существующий проект поддержку Bazel можно так:
ng add @angular/bazel
Можно и создать новое приложение с использованием Bazel:
$ npm install -g @angular/bazel
$ ng new my-app --collection=@angular/bazel
Новая версия Angular позволяет использовать API Builders, известный так же как Architect. Angular использует сборщики (builder) для выполнения основных операций: serve
, build
, test
, lint
и e2e
. Вот пример использования сборщиков из файла angular.json
:
...
"projects": {
"app-name": {
...
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
...
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
...
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
...
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
...
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
...
}
}
}
}
Теперь можно создавать собственные сборщики. Мне они видятся подобными командам gulp/grunt, используемым в «прежние времена».
В целом, сборщик — это просто функция с набором команд, которую передают методу createBuilder()
из пакета @angular-devkit/architect
:
import { createBuilder } from '@angular-devkit/architect';
function customBuild(options, context) {
return new Promise((resolve, reject) => {
// набор команд
})
}
createBuilder(customBuild);
На встроенные сборщики Angular можно взглянуть здесь [7]. Вот [8] отличный материал о них в блоге Angular.
В новой версии Angular будет и новая версия системы ленивой загрузки модулей, появление которой приводит к тому, что существующий синтаксис loadChildren:string
будет признан устаревшим.
Раньше это выглядело так:
loadChildren: './lazy/lazy.module#LazyModule';
С выходом Angular 8 — так:
loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule)
Если у вас есть множество модулей, при работе с которыми применяется механизм ленивой загрузки, и вы хотите автоматизировать их перевод в новый режим работы — взгляните на этот [9] материал.
Команда разработчиков Angular стремится к тому, чтобы поддержать тех, кто пользуется AngularJS и помочь им перейти на Angular. В результате в систему, в пакет angular/common/upgrade
, добавлена поддержка сервиса $location
. Речь идёт о следующих возможностях:
$location
.hostname
, protocol
, port
, search
).В Angular 8 добавлена поддержка веб-воркеров. С их помощью можно организовать фоновое выполнение ресурсоёмкого кода. Для того чтобы создать новый веб-воркер можно воспользоваться следующей командой интерфейса командной строки Angular:
ng g webWorker <name>
Так как в последнее время наблюдается серьёзный рост популярности прогрессивных веб-приложений, было сделано множество улучшений сервис-воркеров. В частности, одним из таких улучшений стало добавление параметра SwRegistrationOptions
. Ещё одним улучшением стала поддержка нескольких приложений на одном домене.
Почитать подробности о сервис-воркерах можно в этом [10] разделе документации Angular.
Добавлен метод markAllAsTouched
, который позволяет отметить все элементы внутри FormGroup
как touched
. Это весьма полезно в тех случаях, если нужно запустить валидацию всех элементов управления внутри FormGroup
. До этого то же самое делалось так:
validateFormAndDisplayErrors(form: FormGroup) {
Object.keys(form.controls).map((controlName) => {
form.get(controlName).markAsTouched({onlySelf: true});
});
}
В новом Angular для очистки FormArray
можно воспользоваться методом clear
, который удаляет из него все элементы. Ранее нужно было пользоваться следующей конструкцией, удаляя первый элемент в каждой итерации цикла:
while (formArray.length) {
formArray.removeAt(0);
}
Больше так делать не придётся. Теперь достаточно вызвать единственный метод:
formArray.clear()
Эта новая возможность подразумевает использование флага static
, который позволяет указать момент разрешения запроса, определяемого директивой ViewChild
или ContentChild
.
Возможно, вы сталкивались со следующими примерами непоследовательного поведения системы. Иногда результаты поиска доступны в методе жизненного цикла ngOnInit
, а иногда их нет до вызова ngAfterContentInit
или ngAfterViewInit
. Вот как пользоваться флагом static
:
// Обеспечивает проведение обнаружения изменений перед предоставлением доступа к элементу
@ContentChild('foo', { static: false }) foo!: ElementRef;
// Позволяет получить доступ к элементу в методе жизненного цикла ngOnInit
@ViewChild(TemplateRef, { static: true }) foo!: TemplateRef;
Надо отметить, что эти возможности недоступны для директив ViewChildren
и ContentChildren
. Соответствующие им запросы на поиск элементов выполняются после выполнения обнаружения изменений.
При использовании static: true
стоит проявлять осторожность, так как применение этого флага не позволит получать результаты из динамических шаблонов (то есть *ngIf). В систему добавлено правило Schematics, позволяющее перевести существующий код на использование нового синтаксиса. Этот синтаксис будет использоваться с Ivy.
→ Подробности об этой возможности можно почитать здесь [11].
Angular теперь использует TypeScript 3.4 (в седьмой версии Angular применяется TypeScript 3.2.x). В новой версии TS не так уж и много серьёзных изменений. Они, вероятно, не приведут к неприятным последствиям.
→ Подробности о новшествах TS 3.4 можно узнать здесь [12].
В текущих условиях ServerRendererFactory2
создаёт новый экземпляр DomElementSchemaRegistry
для каждого запроса, что довольно затратно в плане ресурсов. Теперь же будет организовано совместное использование глобального экземпляра DomElementSchemaRegistry
.
Если вы пользуетесь
ng run [PROJECT_NAME]:deploy
→ Тут [14] можно узнать подробности об этой возможности.
Метод TesBed.get
имел две сигнатуры. Одна — типизированная, вторая — принимающая и возвращающая тип any
. Теперь сигнатура метода, предусматривающая применение типа any
, признана устаревшей. Пользоваться этим методом можно только с указанием конкретного типа. Это, например, окажет воздействие на случаи работы со строковыми токенами (которые не поддерживаются) и с некоторыми другими токенами.
Раньше использовались такие конструкции:
TestBed.configureTestingModule({
providers: [{ provide: "stringToken", useValue: new Service() }],
});
let service = TestBed.get("stringToken"); // тип any
Теперь применяется следующий подход:
const SERVICE_TOKEN = new InjectionToken<Service>("SERVICE_TOKEN");
TestBed.configureTestingModule({
providers: [{provide: SERVICE_TOKEN, useValue: new Service()}],
});
let service = TestBed.get(SERVICE_TOKEN); // тип Service
Из пакета @angular/platform-browser
удаляют DOCUMENT
. Если вы пользуетесь DOCUMENT
из этого пакета — вам стоит начать импортировать его из @angular/common
.
Пакет @angular/http
был признан устаревшим в Angular 5, но был всё ещё доступен, так как @angular/platform-server
был от него зависим. Теперь этот пакет удаляют из списка пакетов.
Немногие знают о том, что Angular автоматически исправлял ошибки при использовании HTML-элементов tr
и col
.
В случае с tr
исправления выполнялись в том случае, если соответствующий элемент не находился внутри тега tbody
, tfoot
или thead
. Исправления заключались в автоматическом помещении элемента в tbody
.
В случае с col
исправлениям подвергался код, в котором этот элемент не находится внутри тега colgroup
.
Теперь Angular оставляет исправление этих ошибок на усмотрение разработчиков. Делается это для того чтобы избежать конфликтов и ошибок. Как результат, тем, кто привык к этой возможности, нужно будет заботиться о правильности кода самостоятельно.
→ Подробности об этом можно почитать здесь [16].
Проект Angular Material переименован в Angular Components. Имена пакетов не изменились.
Angular 8 выйдет уже очень скоро. Команда разработчиков Angular делает большое дело. Результаты их усилий облегчают работу и жизнь тех, кто пользуется Angular. В частности, например, с каждой новой версией фреймворка всё проще и проще выполнять переход на неё с предыдущей версии. Вот, например, как это выглядит в случае с Air France.
Время, необходимое для перехода на новые версии Angular (источник [2])
В результате можно надеяться на то, что переход с Angular 7 на Angular 8 не займёт много времени и не потребует серьёзных усилий.
Автор: ru_vds
Источник [17]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/318960
Ссылки в тексте:
[1] Image: https://habr.com/ru/company/ruvds/blog/453584/
[2] докладе: https://youtu.be/O0xx5SvjmnU
[3] nomodule: https://html.spec.whatwg.org/multipage/scripting.html#attr-script-nomodule
[4] Вот: https://youtu.be/FiVw6zjgw24
[5] документацию: https://bazel.build/
[6] Angular: https://next.angular.io/guide/bazel
[7] здесь: https://github.com/angular/angular-cli/tree/a41c18571370a164d8a36695dbf4faf65860fc19/packages/angular_devkit/build_angular/src
[8] Вот: https://blog.angular.io/introducing-cli-builders-d012d4489f1b
[9] этот: https://blog.angularindepth.com/automatically-upgrade-lazy-loaded-angular-modules-for-ivy-e760872e6084
[10] этом: https://next.angular.io/guide/service-worker-config
[11] здесь: https://github.com/angular/angular/pull/28810
[12] здесь: https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#typescript-34
[13] хостингом: https://www.reg.ru/?rlink=reflink-717
[14] Тут: https://github.com/angular/angularfire2/pull/2046/files#diff-f2708892333baee7be9359746cdb7939
[15] angular: https://habr.com/ru/users/angular/
[16] здесь: https://github.com/angular/angular/commit/f2dc32e
[17] Источник: https://habr.com/ru/post/453584/?utm_campaign=453584
Нажмите здесь для печати.