Ленивая загрузка функциональных модулей¶
7.05.2022
По умолчанию NgModules загружаются с нетерпением. Это означает, что как только приложение загружается, загружаются и все модули NgModules, независимо от того, нужны они сразу или нет. Для больших приложений с большим количеством маршрутов рассмотрите вариант ленивой загрузки — шаблон проектирования, который загружает NgModules по мере необходимости.
Ленивая загрузка помогает уменьшить размер начальных пакетов, что, в свою очередь, сокращает время загрузки.
Окончательный пример приложения с двумя лениво загружаемыми модулями, который описан на этой странице, смотрите в коде.
Основы ленивой загрузки¶
В этом разделе представлена основная процедура настройки маршрута с ленивой загрузкой. Пошаговый пример смотрите в разделе пошаговая настройка на этой странице.
Для ленивой загрузки модулей Angular используйте loadChildren
(вместо component
) в конфигурации маршрутов
вашего AppRoutingModule
следующим образом.
1 2 3 4 5 6 7 8 9 |
|
В модуле маршрутизации модуля lazy-loaded добавьте маршрут для компонента.
1 2 3 4 5 6 |
|
Также не забудьте удалить ItemsModule
из AppModule
. Для получения пошаговых инструкций по ленивой загрузке модулей, продолжите следующие разделы этой страницы.
Пошаговая настройка¶
Установка функционального модуля с ленивой загрузкой требует двух основных шагов:
-
Создайте функциональный модуль с помощью Angular CLI, используя флаг
--route
. -
Настройте маршруты.
Настройка приложения¶
Если у вас еще нет приложения, выполните следующие шаги, чтобы создать его с помощью Angular CLI. Если у вас уже есть приложение, перейдите к разделу Настройка маршрутов.
Введите следующую команду, где customer-app
— имя вашего приложения:
1 |
|
Это создает приложение под названием customer-app
, а флаг --routing
создает файл app-routing.module.ts
. Это один из файлов, необходимых для настройки ленивой загрузки для вашего функционального модуля. Перейдите в проект, выполнив команду cd customer-app
.
Опция --routing
требует Angular CLI версии 8.1 или выше. Смотрите Keeping Up to Date.
Создание функционального модуля с маршрутизацией¶
Далее вам понадобится функциональный модуль с компонентом для маршрутизации. Чтобы создать такой модуль, введите в командной строке следующую команду, где customers
— имя функционального модуля.
Путь для загрузки функциональных модулей customers
также customers
, поскольку он указан с опцией --route
:
1 |
|
Это создаст директорию customers
, содержащую новый функциональный модуль CustomersModule
, определяемый в файле customers.module.ts
, и модуль маршрутизации CustomersRoutingModule
, определяемый в файле customers-routing.module.ts
. Команда автоматически объявляет CustomersComponent
и импортирует CustomersRoutingModule
внутри нового функционального модуля.
Поскольку новый модуль предназначен для ленивой загрузки, команда не добавляет ссылку на него в файл корневого модуля приложения, app.module.ts
. Вместо этого она добавляет объявленный маршрут customers
в массив routes
, объявленный в модуле, предоставленном в качестве опции --module
.
1 2 3 4 5 6 7 8 9 |
|
Обратите внимание, что синтаксис ленивой загрузки использует loadChildren
, за которым следует функция, использующая встроенный в браузер синтаксис import('...')
для динамического импорта. Путь импорта — это относительный путь к модулю.
Ленивая загрузка на основе строк
В версии 8 Angular строковый синтаксис для спецификации маршрута loadChildren
был устаревшим в пользу синтаксиса import()
. Вы можете отказаться от использования строковой ленивой загрузки (loadChildren: './path/to/module#Module'
), включив маршруты с ленивой загрузкой в ваш файл tsconfig
, который включает файлы с ленивой загрузкой в компиляцию.
По умолчанию Angular CLI генерирует проекты с более строгими включениями файлов, предназначенными для использования с синтаксисом import()
.
Добавьте еще один функциональный модуль¶
Используйте ту же команду для создания второго функционального модуля с ленивой загрузкой и маршрутизацией, а также его компонента-заглушки.
1 |
|
Это создает новый каталог orders
, содержащий OrdersModule
и OrdersRoutingModule
, а также новые исходные файлы OrdersComponent
. Маршрут orders
, указанный с помощью опции --route
, добавляется в массив routes
внутри файла app-routing.module.ts
, используя синтаксис ленивой загрузки.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Настройте пользовательский интерфейс¶
Хотя вы можете ввести URL в адресную строку, навигационный пользовательский интерфейс более прост для пользователя и более распространен. Замените стандартную разметку placeholder в app.component.html
на пользовательскую навигацию, чтобы вы могли переходить к своим модулям в браузере:
1 2 3 4 5 6 7 8 9 |
|
Чтобы увидеть ваше приложение в браузере, введите следующую команду в окне инструмента командной строки:
1 |
|
Затем перейдите на localhost:4200
, где вы должны увидеть "customer-app" и три кнопки.
Эти кнопки работают, потому что Angular CLI автоматически добавил маршруты к модулям функций в массив routes
в файле app-routing.module.ts
.
Импорт и конфигурация маршрутов¶
Angular CLI автоматически добавил каждый функциональный модуль в карту маршрутов на уровне приложения. Завершите это добавлением маршрута по умолчанию.
В файле app-routing.module.ts
обновите массив routes
следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Первые два пути — это маршруты к CustomersModule
и OrdersModule
. Последняя запись определяет маршрут по умолчанию.
Пустой путь соответствует всему, что не соответствует предыдущему пути.
Внутри функционального модуля¶
Далее посмотрите на файл customers.module.ts
. Если вы используете Angular CLI и следуете шагам, описанным на этой странице, вам не нужно ничего здесь делать.
1 2 3 4 5 6 7 8 9 10 |
|
Файл customers.module.ts
импортирует файлы customers-routing.module.ts
и customers.component.ts
. CustomersRoutingModule
указан в массиве @NgModule
imports
, что дает CustomersModule
доступ к собственному модулю маршрутизации.
CustomersComponent
находится в массиве declarations
, что означает, что CustomersComponent
принадлежит CustomersModule
.
Затем app-routing.module.ts
импортирует функциональный модуль customers.module.ts
, используя динамический импорт JavaScript.
Файл определения маршрута для конкретной функции customers-routing.module.ts
импортирует свой компонент функции, определенный в файле customers.component.ts
, вместе с другими операторами импорта JavaScript. Затем он сопоставляет пустой путь с CustomersComponent
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Здесь path
установлен в пустую строку, потому что путь в AppRoutingModule
уже установлен в customers
, поэтому этот маршрут в CustomersRoutingModule
уже находится в контексте customers
. Каждый маршрут в этом модуле маршрутизации является дочерним маршрутом.
Модуль маршрутизации другого функционального модуля настроен аналогично.
1 2 3 4 5 6 7 8 |
|
Проверить ленивую загрузку¶
Вы можете проверить, действительно ли модуль загружается в ленивом режиме, с помощью инструментов разработчика Chrome. В Chrome откройте инструменты разработчика, нажав Cmd+Option+I на Mac или Ctrl+Shift+J на PC, и перейдите на вкладку Network.
Нажмите на кнопку "Заказы" или "Клиенты". Если появится фрагмент, значит, все подключено правильно и функциональный модуль загружается в ленивом режиме.
Кусок должен появиться для Заказов и для Клиентов, но только один раз для каждого.
Чтобы увидеть его снова или проверить после внесения изменений, нажмите на круг с линией в верхней левой части вкладки Сеть:
Затем перезагрузите с помощью Cmd+R или Ctrl+R, в зависимости от вашей платформы.
forRoot()
и forChild()
¶
Вы могли заметить, что Angular CLI добавляет RouterModule.forRoot(routes)
в массив импортов
модуля AppRoutingModule
. Это дает Angular знать, что AppRoutingModule
является модулем маршрутизации, а forRoot()
указывает, что это корневой модуль маршрутизации.
Он настраивает все маршруты, которые вы ему передаете, дает вам доступ к директивам маршрутизации и регистрирует службу Router
.
Используйте forRoot()
только один раз в приложении, внутри AppRoutingModule
.
Angular CLI также добавляет функцию RouterModule.forChild(routes)
к модулям маршрутизации. Таким образом, Angular знает, что список маршрутов отвечает только за предоставление дополнительных маршрутов и предназначен для функциональных модулей.
Вы можете использовать forChild()
в нескольких модулях.
Метод forRoot()
заботится о конфигурации глобального инжектора для маршрутизатора. Метод forChild()
не имеет конфигурации инжектора.
Он использует такие директивы, как RouterOutlet
и RouterLink
.
Дополнительную информацию см. в разделе шаблон forRoot()
руководства Singleton Services.
Предварительная загрузка¶
Предварительная загрузка улучшает UX, загружая части вашего приложения в фоновом режиме. Вы можете предварительно загружать модули, отдельные компоненты или данные компонента.
Предварительная загрузка модулей и отдельных компонентов¶
Предварительная загрузка модулей и отдельных компонентов улучшает UX, загружая части вашего приложения в фоновом режиме. Благодаря этому пользователям не нужно ждать загрузки элементов при активации маршрута.
Чтобы включить предварительную загрузку всех лениво загруженных модулей и автономных компонентов, импортируйте маркер PreloadAllModules
из Angular router
.
Приложение на основе модулей¶
1 |
|
Все еще в AppRoutingModule
, укажите стратегию предварительной загрузки в forRoot()
.
1 2 3 |
|
Автономное приложение¶
Для автономных приложений настройте стратегии предварительной загрузки, добавив withPreloading
к provideRouter
s RouterFeatures в app.config.ts
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Предварительная загрузка данных компонента¶
Чтобы предварительно загрузить данные компонента, используйте резольвер
. Резольверы улучшают UX, блокируя загрузку страницы до тех пор, пока не будут доступны все необходимые данные для полного отображения страницы.
Резольверы¶
Создайте службу резольвера. С помощью Angular CLI команда для создания службы выглядит следующим образом:
1 |
|
Во вновь созданном сервисе реализуйте интерфейс Resolve
, предоставляемый пакетом @angular/router
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Импортируйте этот резольвер в модуль маршрутизации вашего модуля.
1 |
|
Добавьте объект resolve
в конфигурацию route
компонента.
1 2 3 4 5 6 7 |
|
В конструкторе компонента введите экземпляр класса ActivatedRoute
, который представляет текущий маршрут.
1 2 3 4 5 6 |
|
Используйте инжектированный экземпляр класса ActivatedRoute
для доступа к данным
, связанным с данным маршрутом.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Для получения дополнительной информации и рабочего примера смотрите раздел учебника по маршрутизации, посвященный предварительной загрузке.
Устранение неполадок при ленивой загрузке модулей¶
Распространенной ошибкой при ленивой загрузке модулей является импорт общих модулей в несколько мест в приложении. Для проверки этого условия сначала создайте модуль с помощью Angular CLI и включите параметр --route route-name
, где route-name
— это имя вашего модуля.
Затем создайте модуль без параметра --route
.
Если ng generate module
с параметром --route
возвращает ошибку, а без него работает правильно, возможно, вы импортировали один и тот же модуль в нескольких местах.
Помните, что многие общие модули Angular должны быть импортированы в основу вашего приложения.
Для получения дополнительной информации о модулях Angular смотрите NgModules.
Подробнее о NgModules и маршрутизации¶
Вам также может быть интересно следующее:
- Маршрутизация и навигация
- Провайдеры
- Типы модулей функций
- Разделение кода на уровне маршрутов в Angular
- Стратегии предварительной загрузки маршрутов в Angular