В настоящее время я переношу свое мобильное приложение 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 и впервые получат доступ к странице сведений, они столкнутся с меньшей задержкой. или даже почти нет 😉

Надеюсь, это решение может вам немного помочь, если вы хотите предварительно загрузить некоторые маршруты или страницы в свое замечательное приложение 😁