fix(router): fix load interaction of navigation and preload strategie… · angular/angular@bba1981
@@ -7,8 +7,8 @@
77 */
8899import {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';
12121313import {LoadChildren, LoadedRouterConfig, Route} from './config';
1414import {flatten, wrapIntoObservable} from './utils/collection';
@@ -28,27 +28,39 @@ export class RouterConfigLoader {
2828private onLoadEndListener?: (r: Route) => void) {}
29293030load(parentInjector: Injector, route: Route): Observable<LoadedRouterConfig> {
31+if (route._loader$) {
32+return route._loader$;
33+}
34+3135if (this.onLoadStartListener) {
3236this.onLoadStartListener(route);
3337}
34-3538const 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}
53655466private loadModuleFactory(loadChildren: LoadChildren): Observable<NgModuleFactory<any>> {