fix(router): fix load interaction of navigation and preload strategie… · angular/angular@bba1981

@@ -7,8 +7,8 @@

77

*/

8899

import {Compiler, InjectFlags, InjectionToken, Injector, NgModuleFactory, NgModuleFactoryLoader} from '@angular/core';

10-

import {from, Observable, of} from 'rxjs';

11-

import {map, mergeMap} from 'rxjs/operators';

10+

import {ConnectableObservable, from, Observable, of, Subject} from 'rxjs';

11+

import {catchError, map, mergeMap, refCount, tap} from 'rxjs/operators';

12121313

import {LoadChildren, LoadedRouterConfig, Route} from './config';

1414

import {flatten, wrapIntoObservable} from './utils/collection';

@@ -28,27 +28,39 @@ export class RouterConfigLoader {

2828

private onLoadEndListener?: (r: Route) => void) {}

29293030

load(parentInjector: Injector, route: Route): Observable<LoadedRouterConfig> {

31+

if (route._loader$) {

32+

return route._loader$;

33+

}

34+3135

if (this.onLoadStartListener) {

3236

this.onLoadStartListener(route);

3337

}

34-3538

const moduleFactory$ = this.loadModuleFactory(route.loadChildren!);

36-37-

return moduleFactory$.pipe(map((factory: NgModuleFactory<any>) => {

38-

if (this.onLoadEndListener) {

39-

this.onLoadEndListener(route);

40-

}

41-42-

const module = factory.create(parentInjector);

43-44-

// When loading a module that doesn't provide `RouterModule.forChild()` preloader will get

45-

// stuck in an infinite loop. The child module's Injector will look to its parent `Injector`

46-

// when it doesn't find any ROUTES so it will return routes for it's parent module instead.

47-

return new LoadedRouterConfig(

48-

flatten(module.injector.get(ROUTES, undefined, InjectFlags.Self | InjectFlags.Optional))

49-

.map(standardizeConfig),

50-

module);

51-

}));

39+

const loadRunner = moduleFactory$.pipe(

40+

map((factory: NgModuleFactory<any>) => {

41+

if (this.onLoadEndListener) {

42+

this.onLoadEndListener(route);

43+

}

44+

const module = factory.create(parentInjector);

45+

// When loading a module that doesn't provide `RouterModule.forChild()` preloader

46+

// will get stuck in an infinite loop. The child module's Injector will look to

47+

// its parent `Injector` when it doesn't find any ROUTES so it will return routes

48+

// for it's parent module instead.

49+

return new LoadedRouterConfig(

50+

flatten(

51+

module.injector.get(ROUTES, undefined, InjectFlags.Self | InjectFlags.Optional))

52+

.map(standardizeConfig),

53+

module);

54+

}),

55+

catchError((err) => {

56+

route._loader$ = undefined;

57+

throw err;

58+

}),

59+

);

60+

// Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much

61+

route._loader$ = new ConnectableObservable(loadRunner, () => new Subject<LoadedRouterConfig>())

62+

.pipe(refCount());

63+

return route._loader$;

5264

}

53655466

private loadModuleFactory(loadChildren: LoadChildren): Observable<NgModuleFactory<any>> {