Автоматическая миграция на автономные компоненты¶
Хотя новые автономные компоненты могут прекрасно сочетаться с традиционным кодом Angular на основе NgModule, люди могут захотеть полностью перенести свои проекты в новый автономный мир. Начиная с версии Angular 15.2, существует схема, автоматизирующая эту задачу. Она преобразует проекты в 3 шага. После каждого шага мы можем проверить текущий прогресс и вручную позаботиться о деталях, с которыми не справился автоматический процесс.
В этом коротком руководстве я собираюсь пройти эти 3 шага вместе с вами и мигрировать наше демо-приложение.
Если вы хотите воспроизвести эти шаги, вы можете найти начальную ситуацию, основанную на NgModule, в нашем учебнике здесь:
📂 https://github.com/manfredsteyer/standalone-example-cli
(Branch ngmodules
)
Первый взгляд на мигрируемое приложение¶
После проверки ветки ngmodules
(!) вышеупомянутого проекта, возможно, будет хорошей идеей немного порыться в исходном коде. Вы должны узнать следующие модули NgModules:
1 2 3 |
|
Также запустите приложение, чтобы получить первое впечатление о нем:
1 |
|
Шаг 1¶
Теперь давайте запустим схему миграции, доступную в Angular 15.2:
1 |
|
Когда нас спрашивают о типе миграции, мы выбираем первый вариант (ведь это такая милая традиция — "начинать с начала"...).
На вопрос о пути для миграции мы выбираем значение по умолчанию, нажимая клавишу Enter:
Значение по умолчанию ./
указывает на корень проекта. Таким образом, весь проект будет перенесен сразу. Для малых и средних приложений это вполне подходит. Однако для больших приложений может быть интересно переносить проект постепенно.
После этого первого шага вам следует взглянуть на исходный код и проверить, все ли в порядке. В случае с этим примером проекта вам не нужно беспокоиться. Схемы отлично справляются со своей задачей!
Шаг 2¶
Теперь давайте снова запустим схему для второго шага:
Вывод показывает, что SharedModule
был удален, а остальные модули были обновлены. Нет ничего страшного в том, что AppModule
все еще на месте — он будет удален на 3-м шаге. Однако все остальные модули NgModules уже должны быть удалены. К сожалению, модуль FlightBookingModule
все еще здесь:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Как видно из этого листинга, модуль FlightBookingModule
больше ничего не делает. Однако есть несколько вызовов методов в секции imports
. Эти методы предназначены для настройки маршрутизатора и хранилища NGRX. Поскольку они довольно специфичны для библиотеки, схема не смогла преобразовать их в вызовы эквивалентных Standalone API. Поэтому нам придется позаботиться об этом вручную.
RouterModule.forChild
устанавливает несколько дочерних маршрутов, которые загружаются вместе с FlightBookingModule
. Однако в автономном мире нам больше не нужны NgModules для настройки дочерних маршрутов. Вместо этого конфигурация родительской маршрутизации может прямо указывать на дочерние маршруты. Поэтому давайте перейдем в файл app.routes.ts
и обновим маршрут, запускающий ленивую загрузку:
1 2 3 4 5 6 7 8 9 |
|
Обратите внимание, что import
теперь напрямую импортирует маршруты бронирования авиабилетов. Больше нет перенаправления через FlightBookingModule
. Есть даже возможность сократить это еще больше: Если файл flight-booking.routes.ts
экспортирует маршруты как default export, мы можем пропустить последующий вызов then
:
1 2 3 4 5 6 |
|
Чтобы убедиться, что хранилище NGRX инициализировано для этой ленивой части приложения, мы можем зарегистрировать соответствующих провайдеров непосредственно для ленивых дочерних маршрутов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
Этот новый массив провайдеров устанавливает сервисы, необходимые только для данного маршрута и его дочерних элементов. Функция importProvidersFrom
перебрасывает мост в мир NgModules и позволяет получить их провайдеров.
Теперь мы можем удалить модуль FlightBookingModule
(src/app/booking/flight-booking.module.ts
).
Шаг 3¶
Запустим нашу схему миграции в 3-й раз:
Это удаляет AppModule
и обновляет файл main.ts
для прямой загрузки AppComponent
. После этого шага приложение должно работать как прежде:
1 |
|
Бонус: переход на автономные API¶
Заглянув в main.ts
, мы увидим, что он по-прежнему ссылается на несколько модулей с помощью importProvidersFrom
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
Кроме того, существует традиционный класс-перехватчик HttpInterceptor
, о котором HttpClient
узнает с помощью вызова withInterceptorsFromDi
. Переход на автономные API позволяет улучшить эту ситуацию:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
Эта модификация решает следующие задачи:
- Удаление импорта
BrowserModule
, который не нужно явно импортировать при загрузке Standalone Component. - Установка пользовательской библиотеки Logger с помощью
provideLogger
. - Настройка магазина NGRX с помощью
provideStore
,provideEffects
иprovideStoreDevtools
. - Замена традиционного
HttpInterceptor
на функциональный перехватчик, который теперь передается вwithInterceptors
. Чтобы облегчить этот шаг, функциональный аналог уже был частью кодовой базы с самого начала.
Более подробную информацию о пользовательских Standalone API, таких как provideLogger, можно найти здесь.
NGRX ожидает, что его Standalone API будут использоваться полностью или не будут использоваться вообще. Следовательно, нам также нужно вернуться к flight-booking.routes.ts
и заменить вызов importProvidersFrom
на вызовы provideState
и provideEffects
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Обратите внимание, что в то время как мы вызываем provideStore
в main.ts
для настройки магазина, нам нужно вызвать provideState
(!) в дальнейших частях приложения, чтобы настроить для них дополнительные фрагменты функций. Однако provideEffects
можно вызвать в обоих местах, чтобы установить эффекты не только для корневого уровня, но и для функциональных срезов.
После этой модификации приложение переносится на Standalone Components and APIs. Запустите его через
1 |
|
Заключение¶
Новые схемы автоматизируют переход на Standalone Components. В три шага все приложение или только его часть переходит на новый облегченный способ работы с Angular. После каждого шага мы можем проверить выполненную модификацию и вмешаться.