В настоящее время я переношу свое мобильное приложение Fluster с Ionic v3 на v4. Как вы могли видеть в следующем видео, в самый первый раз, когда пользователь получит доступ к странице сведений, он / она столкнется с небольшой задержкой 😔 Причина этого проста: оставшиеся (или еще не загруженные) модули ленивый маршрут Angular все еще должен быть загружен
К счастью, Angular v6 предлагает возможность предварительной загрузки всех или выбранных модулей. Об этом много раз писали, например, в интересной статье Адриан Фачу.
Однако различных решений, представленных во всех этих руководствах, было недостаточно или было недостаточно для моего варианта использования.
Проблемы
Сначала я попробовал готовую стратегию Angular PreloadAllModules, которая, поверьте мне или нет, негативно повлияла на мою загрузку, сделав ее медленнее 😱 чего, конечно, я бы избегал любой ценой, так как медленная загрузка была одной из них. моего заклятого врага
Затем я попробовал стратегию предварительной загрузки только модуля моей страницы с подробностями. К сожалению, опять же, результаты не оправдали моих ожиданий. Модули были загружены слишком рано по отношению к моему потоку или были загружены одновременно с модулем главной страницы, что опять же замедлило мою загрузку 😢
Столкнувшись с этой ситуацией, я попробовал решение, описанное Адрианом Фачу, которое работало хорошо, но только с некоторым расширением. Модули страницы с подробностями были эффективно загружены впоследствии, но у меня было ощущение, что загрузка модулей после задержки была немного «случайной» для моего конкретного случая.
Решение
К счастью, вместе с Аароном Стерлингом, обмениваясь на Ionic Forum, мы смогли найти решение, которое соответствовало моим потребностям 😃 Я очень сообщество Ionic
Идея заключалась в том, чтобы реализовать пользовательскую стратегию предварительной загрузки и запускать ее только по запросу соответственно, в моем случае, чтобы начать предварительную загрузку, когда моя главная страница будет готова.
Реализация решения
Прежде всего, нам нужен новый провайдер, который будет собирать маршруты, которые мы, возможно, захотим предварительно загрузить, и предлагающий возможность предварительной загрузки определенного маршрута по запросу.
import {PreloadingStrategy, Route} from '@angular/router'; import {Observable, of} from 'rxjs'; import {Injectable} from '@angular/core'; export interface RouteToPreload { routePath: string; route: Route; load: Function; } @Injectable({ providedIn: 'root' }) export class AppRoutingPreloaderService implements PreloadingStrategy { private routesToPreload: RouteToPreload[] = []; constructor() { } preload(route: Route, load: Function): Observable<any> { if (route.data && route.data.preload) { this.routesToPreload.push({ routePath: route.path, route: route, load: load }); } return of(null); } preloadRoute(path: string): Promise<void> { return new Promise<void>((resolve) => { if (this.routesToPreload && this.routesToPreload.length > 0) { const routeToPreload: RouteToPreload = this.routesToPreload.find( (filterRouteToPreload: RouteToPreload) => filterRouteToPreload.routePath === path); if (routeToPreload) { routeToPreload.load(); } } resolve(); }); } }
Примечание: в настоящее время провайдер может загружаться дважды и, следовательно, собирать дважды маршруты. Здесь нет такой проблемы, потому что по умолчанию мы ничего не загружаем предварительно, а эффективная предварительная загрузка позаботится только о загрузке первого маршрута, который был собран
Затем, как описано в других статьях, мы могли бы изменить наш app-routing.module.ts
, чтобы предоставить нашу собственную стратегию предварительной загрузки и указать, какие маршруты являются кандидатами для предварительной загрузки.
const routes: Routes = [ { path: 'main', loadChildren: './pages/main.module#MainPageModule' }, { path: 'detail', loadChildren: './pages/detail.module#DetailPageModule', data: {preload: true} } ]; @NgModule({ imports: [RouterModule.forRoot(routes, {preloadingStrategy: AppRoutingPreloaderService})], exports: [RouterModule] }) export class AppRoutingModule { }
Наконец, позвольте волшебству произойти ✨, мы могли бы использовать поставщика на нашей выбранной странице, где мы хотели бы запускать предварительную загрузку по запросу, например, начиная с жизненного цикла по нашему выбору, такого как ionViewDidEnter
или afterViewChecked
@Component({ selector: 'app-main', templateUrl: './main.page.html', styleUrls: ['./main.page.scss'], }) export class ItemsPage { constructor(private routingService: AppRoutingPreloaderService) {} async ionViewDidEnter() { await this.routingService.preloadRoute('details'); } }
При этом, как вы можете видеть на следующем снимке экрана, модули моей страницы с подробными сведениями предварительно загружаются плавно после того, как мое приложение успешно загрузилось, и после того, как главная страница была отображена и настроена, она готова к взаимодействиям.
Вуаля ✌️ Решение все еще нуждается в дополнительном тестировании на реальных устройствах, но я уверен, что с этого момента, когда мои пользователи будут использовать мое приложение Ionic v4 и впервые получат доступ к странице сведений, они столкнутся с меньшей задержкой. или даже почти нет 😉
Надеюсь, это решение может вам немного помочь, если вы хотите предварительно загрузить некоторые маршруты или страницы в свое замечательное приложение 😁