fix(router): attempt to resolve component resources in JIT mode (#63062)

In #62758 we started loading the component resources during bootstrap in JIT mode to ensure that they're in place by the time we create the component. This won't work for lazy-loaded components in the router, because they don't exist at bootstrap time.

These changes add similar logic when the router loads a component.

PR Close #63062
This commit is contained in:
Kristiyan Kostadinov 2025-08-08 10:45:43 +02:00 committed by Andrew Scott
parent 3b214d2040
commit 660444fbf2
2 changed files with 21 additions and 1 deletions

View file

@ -903,6 +903,7 @@
"matchWithChecks",
"materializeViewResults",
"matrixParamsMatch",
"maybeResolveResources",
"maybeReturnReactiveLViewConsumer",
"maybeSchedule",
"maybeUnwrapDefaultExport",

View file

@ -16,9 +16,10 @@ import {
NgModuleFactory,
runInInjectionContext,
Type,
ɵresolveComponentResources as resolveComponentResources,
} from '@angular/core';
import {ConnectableObservable, from, Observable, of, Subject} from 'rxjs';
import {finalize, map, mergeMap, refCount, tap} from 'rxjs/operators';
import {finalize, map, mergeMap, refCount, switchMap, tap} from 'rxjs/operators';
import {DefaultExport, LoadedRouterConfig, Route, Routes} from './models';
import {wrapIntoObservable} from './utils/collection';
@ -61,6 +62,7 @@ export class RouterConfigLoader {
runInInjectionContext(injector, () => route.loadComponent!()),
).pipe(
map(maybeUnwrapDefaultExport),
switchMap(maybeResolveResources),
tap((component) => {
if (this.onLoadEndListener) {
this.onLoadEndListener(route);
@ -130,6 +132,7 @@ export function loadChildren(
runInInjectionContext(parentInjector, () => route.loadChildren!()),
).pipe(
map(maybeUnwrapDefaultExport),
switchMap(maybeResolveResources),
mergeMap((t) => {
if (t instanceof NgModuleFactory || Array.isArray(t)) {
return of(t);
@ -177,3 +180,19 @@ function maybeUnwrapDefaultExport<T>(input: T | DefaultExport<T>): T {
// subject to property renaming, so we reference it with bracket access.
return isWrappedDefaultExport(input) ? input['default'] : input;
}
function maybeResolveResources<T>(value: T): Promise<T> | Observable<T> {
// In JIT mode we usually resolve the resources of components on bootstrap, however
// that won't have happened for lazy-loaded components. Attempt to load any pending
// resources again here.
if ((typeof ngJitMode === 'undefined' || ngJitMode) && typeof fetch === 'function') {
return resolveComponentResources(fetch)
.catch((error) => {
console.error(error);
return Promise.resolve();
})
.then(() => value);
}
return of(value);
}