From 8f708b561cbd288845d1500463e9f4e84197f2a9 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 5 Aug 2020 16:06:30 +0000 Subject: [PATCH] fix(router): defer loading of wildcard module until needed (#38348) Defer loading the wildcard module so that it is not loaded until subscribed to. This fixes an issue where it was being eagerly loaded. As an example, wildcard module loading should only occur after all other potential matches have been exhausted. A test case for this was also added to demonstrate the fix. Fixes #25494 PR Close #38348 --- packages/router/src/apply_redirects.ts | 13 +++++++------ packages/router/test/apply_redirects.spec.ts | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/packages/router/src/apply_redirects.ts b/packages/router/src/apply_redirects.ts index 6827c0b005..5eb4050473 100644 --- a/packages/router/src/apply_redirects.ts +++ b/packages/router/src/apply_redirects.ts @@ -7,7 +7,7 @@ */ import {Injector, NgModuleRef} from '@angular/core'; -import {EmptyError, Observable, Observer, of} from 'rxjs'; +import {defer, EmptyError, Observable, Observer, of} from 'rxjs'; import {catchError, concatAll, first, map, mergeMap, tap} from 'rxjs/operators'; import {LoadedRouterConfig, Route, Routes} from './config'; @@ -247,11 +247,12 @@ class ApplyRedirects { segments: UrlSegment[]): Observable { if (route.path === '**') { if (route.loadChildren) { - return this.configLoader.load(ngModule.injector, route) - .pipe(map((cfg: LoadedRouterConfig) => { - route._loadedConfig = cfg; - return new UrlSegmentGroup(segments, {}); - })); + return defer( + () => this.configLoader.load(ngModule.injector, route) + .pipe(map((cfg: LoadedRouterConfig) => { + route._loadedConfig = cfg; + return new UrlSegmentGroup(segments, {}); + }))); } return of(new UrlSegmentGroup(segments, {})); diff --git a/packages/router/test/apply_redirects.spec.ts b/packages/router/test/apply_redirects.spec.ts index 918d259ce0..d564727a88 100644 --- a/packages/router/test/apply_redirects.spec.ts +++ b/packages/router/test/apply_redirects.spec.ts @@ -9,6 +9,7 @@ import {NgModuleRef} from '@angular/core'; import {TestBed} from '@angular/core/testing'; import {Observable, of} from 'rxjs'; +import {delay} from 'rxjs/operators'; import {applyRedirects} from '../src/apply_redirects'; import {LoadedRouterConfig, Route, Routes} from '../src/config'; @@ -435,6 +436,25 @@ describe('applyRedirects', () => { }); }); + it('should not load the configuration of a wildcard route if there is a match', () => { + const loadedConfig = new LoadedRouterConfig([{path: '', component: ComponentB}], testModule); + + const loader = jasmine.createSpyObj('loader', ['load']); + loader.load.and.returnValue(of(loadedConfig).pipe(delay(0))); + + const config: Routes = [ + {path: '', loadChildren: 'matchChildren'}, + {path: '**', loadChildren: 'children'}, + ]; + + applyRedirects(testModule.injector, loader, serializer, tree(''), config).forEach(r => { + expect(loader.load.calls.count()).toEqual(1); + expect(loader.load.calls.first().args).not.toContain(jasmine.objectContaining({ + loadChildren: 'children' + })); + }); + }); + it('should load the configuration after a local redirect from a wildcard route', () => { const loadedConfig = new LoadedRouterConfig([{path: '', component: ComponentB}], testModule);