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
This commit is contained in:
parent
e34c33cd46
commit
8f708b561c
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Injector, NgModuleRef} from '@angular/core';
|
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 {catchError, concatAll, first, map, mergeMap, tap} from 'rxjs/operators';
|
||||||
|
|
||||||
import {LoadedRouterConfig, Route, Routes} from './config';
|
import {LoadedRouterConfig, Route, Routes} from './config';
|
||||||
|
@ -247,11 +247,12 @@ class ApplyRedirects {
|
||||||
segments: UrlSegment[]): Observable<UrlSegmentGroup> {
|
segments: UrlSegment[]): Observable<UrlSegmentGroup> {
|
||||||
if (route.path === '**') {
|
if (route.path === '**') {
|
||||||
if (route.loadChildren) {
|
if (route.loadChildren) {
|
||||||
return this.configLoader.load(ngModule.injector, route)
|
return defer(
|
||||||
|
() => this.configLoader.load(ngModule.injector, route)
|
||||||
.pipe(map((cfg: LoadedRouterConfig) => {
|
.pipe(map((cfg: LoadedRouterConfig) => {
|
||||||
route._loadedConfig = cfg;
|
route._loadedConfig = cfg;
|
||||||
return new UrlSegmentGroup(segments, {});
|
return new UrlSegmentGroup(segments, {});
|
||||||
}));
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
return of(new UrlSegmentGroup(segments, {}));
|
return of(new UrlSegmentGroup(segments, {}));
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
import {NgModuleRef} from '@angular/core';
|
import {NgModuleRef} from '@angular/core';
|
||||||
import {TestBed} from '@angular/core/testing';
|
import {TestBed} from '@angular/core/testing';
|
||||||
import {Observable, of} from 'rxjs';
|
import {Observable, of} from 'rxjs';
|
||||||
|
import {delay} from 'rxjs/operators';
|
||||||
|
|
||||||
import {applyRedirects} from '../src/apply_redirects';
|
import {applyRedirects} from '../src/apply_redirects';
|
||||||
import {LoadedRouterConfig, Route, Routes} from '../src/config';
|
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, <any>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', () => {
|
it('should load the configuration after a local redirect from a wildcard route', () => {
|
||||||
const loadedConfig = new LoadedRouterConfig([{path: '', component: ComponentB}], testModule);
|
const loadedConfig = new LoadedRouterConfig([{path: '', component: ComponentB}], testModule);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue