Upgrading @angular/router 17 to 18
Breaking17.3.12 โ 18.2.14Breaking35Security1Platform1Deprecated10New41Changed5Fixed222Other6
BreakingUpgrade verdict
30 breaking changes and a platform requirement change and a security fix.
In plain terms
- Server-side apps now receive a context object when bootstrapping instead of using a shared global platform.
- Tests using fakeAsync will now run any pending timers when the test function finishes, unless you turn this off.
- A long-deprecated animation method is gone, so any code still calling it will break.
- Two deprecated platform-check functions are removed, so code using them must be updated.
Must act Top 5 of 42 that need code or config changes
Node.js requirement changed in 18.1.0-next.1: ^18.13.0 || >=20.9.0 โ ^18.19.1 || ^20.11.1 || >=22.0.0.
What you must change
Breaking30
Introduces
BootstrapContext for server bootstrapping, removing reliance on a global platform injector.BootstrapContextbootstrapApplicationgetPlatform()destroyPlatform()fakeAsync now flushes pending timers at the end of the given function by default; use {flush: false} to opt out.
fakeAsyncRemoves deprecated
matchesElement from AnimationDriver.AnimationDrivermatchesElementRemoves deprecated
isPlatformWorkerApp and isPlatformWorkerUi APIs.isPlatformWorkerAppisPlatformWorkerUiRemoves support for unassignable expressions in two-way bindings.
Removes deprecated transfer state APIs.
StateKeyTransferStatemakeStateKeyRemoves deprecated Testability methods.
TestabilityRemoves the unused
RESOURCE_CACHE_PROVIDER API from platform-browser-dynamic.RESOURCE_CACHE_PROVIDERRemoves the deprecated
platformDynamicServer API from platform-server.platformDynamicServerRemoves the deprecated
ServerTransferStateModule API from platform-server.ServerTransferStateModuleRemoves deprecated
useAbsoluteUrl and baseUrl from PlatformConfig.PlatformConfiguseAbsoluteUrlbaseUrlRemoves legacy URL handling logic from platform-server.
Angular no longer supports TypeScript versions older than 5.4.
ComponentFixture autoDetect no longer refreshes OnPush host views that are not dirty.ComponentFixtureautoDetectOnPushmarkForCheckChangeDetectionStrategy.DefaultExcludes authenticated HTTP requests from transfer caching by default; opt out with
includeRequestsWithAuthHeaders.withHttpTransferCacheincludeRequestsWithAuthHeadersRemoves deprecated Testability methods increasePendingRequestCount, decreasePendingRequestCount and getPendingRequestCount.
increasePendingRequestCountdecreasePendingRequestCountgetPendingRequestCountAngular only supports writable expressions inside two-way bindings.
OnPush root views must be marked dirty for host bindings to refresh.OnPushGuards can now return RedirectCommand for redirects in addition to UrlTree, so code expecting only boolean or UrlTree in Route types must be adjusted.
RedirectCommandUrlTreeRouteAllows Route.redirectTo to be a function in addition to a string, so code expecting only a string must be adjusted.
Route.redirectToRouteGuard redirects via UrlTree now use replaceUrl when the initial navigation used replaceUrl; use RedirectCommand to customize options.
UrlTreereplaceUrlNavigationBehaviorOptionsRedirectCommandProviders for routed components now always come from the route injector hierarchy and never inherit from the RouterOutlet.
RouterOutletNgModuleprovidersCompletes the removal of the deprecated
async function; use waitForAsync instead.asyncwaitForAsyncComponentFixture.whenStable now matches ApplicationRef.isStable, including unfinished router navigations and HttpClient requests.
ComponentFixture.whenStableApplicationRef.isStableHttpClientHttpTestingController.verify()ComponentFixture.isStable now always switches to true asynchronously instead of synchronously in some scenarios.
ComponentFixture.isStableChange detection keeps refreshing views attached to ApplicationRef that remain marked for check, which can surface NG0103 infinite loops.
ApplicationRefChangeDetectorRef.detectChangesNG0103Change detection timing with event or run coalescing in NgZone is now the first of setTimeout or requestAnimationFrame.
NgZonesetTimeoutrequestAnimationFrameafterNextRenderNewly created views marked for check and reattached during change detection are now guaranteed to refresh in that same cycle.
ExpressionChangedAfterItHasBeenCheckedErrorAngular now runs change detection even when state updates originate outside the zone, which may add change detection rounds in tests.
provideZoneChangeDetection()NgZoneSchedulingMode.NgZoneOnlybootstrapApplication()bootstrapModule()BootstrapOptionsComponentFixture.autoDetect now runs change detection within ApplicationRef.tick, changing refresh order in tests.
ComponentFixture.autoDetectApplicationRef.tickSecurity1
Addresses Trusted Types violations in @angular/upgrade.
@angular/upgradePlatform1
Drops support for TypeScript versions older than 5.4.
Deprecations to plan for
Deprecated10
Deprecates the ignoreChangesOutsideZone option.
ignoreChangesOutsideZoneAdds back the phase flag option as a deprecated API.
Deprecates Local Data API functions.
Deprecates @Component.interpolation.
@Component.interpolationDeprecates HttpClientModule and related modules.
HttpClientModuleDeprecates getCurrencySymbol and related locale currency, date, number, and plural formatting functions.
getCurrencySymbolgetLocaleCurrencyCodegetLocaleCurrencyNamegetLocaleCurrencySymbolgetLocaleDateFormatgetLocaleDateTimeFormatgetLocaleDayNamesgetLocaleDayPeriodsDeprecates @Component.interpolation in favor of Angular's delimiters.
@Component.interpolationDeprecates HttpClientModule, HttpClientXsrfModule and HttpClientJsonpModule, which can be replaced by provider functions only.
HttpClientModuleHttpClientXsrfModuleHttpClientJsonpModuleDeprecates
@Component.interpolation in favor of Angular's delimiters.@Component.interpolationDeprecates
HttpClientModule and related modules in favor of provider functions.HttpClientModuleHttpClientXsrfModuleHttpClientJsonpModuleAPI changes
Generated by DepDelta from published .d.ts files. Not mixed with prose notes.
- removed:
property OutletContext.injector: EnvironmentInjector | null - changed:
function mapToCanActivate(providers: Array<Type<{ canActivate: CanActivateFn }>>): CanActivateFn[] โ function mapToCanActivate(providers: Array<Type<CanActivate>>): CanActivateFn[] - changed:
function mapToCanActivateChild(providers: Array<Type<{ canActivateChild: CanActivateChildFn }>>): CanActivateChildFn[] โ function mapToCanActivateChild(providers: Array<Type<CanActivateChild>>): CanActivateChildFn[] - changed:
function mapToCanDeactivate<T = unknown>(providers: Array<Type<{ canDeactivate: CanDeactivateFn<T> }>>): CanDeactivateFn<T>[] โ function mapToCanDeactivate<T = unknown>(providers: Array<Type<CanDeactivate<T>>>): CanDeactivateFn<T>[] - changed:
function mapToCanMatch(providers: Array<Type<{ canMatch: CanMatchFn }>>): CanMatchFn[] โ function mapToCanMatch(providers: Array<Type<CanMatch>>): CanMatchFn[] - changed:
function mapToResolve<T>(provider: Type<{ resolve: ResolveFn<T> }>): ResolveFn<T> โ function mapToResolve<T>(provider: Type<Resolve<T>>): ResolveFn<T> - changed:
function withNavigationErrorHandler(fn: (error: NavigationError) => void): NavigationErrorHandlerFeature โ function withNavigationErrorHandler(handler: (error: NavigationError) => unknown | RedirectCommand): NavigationErrorHandlerFeature - changed:
method RouterLink.ngOnChanges(changes: SimpleChanges): void โ method RouterLink.ngOnChanges(changes?: SimpleChanges): void - changed:
method RouterLinkWithHref.ngOnChanges(changes: SimpleChanges): void โ method RouterLinkWithHref.ngOnChanges(changes?: SimpleChanges): void - changed:
method RouterOutlet.activateWith(activatedRoute: ActivatedRoute, environmentInjector?: EnvironmentInjector | null): void โ method RouterOutlet.activateWith(activatedRoute: ActivatedRoute, environmentInjector: EnvironmentInjector): void - changed:
method RouterOutletContract.activateWith(activatedRoute: ActivatedRoute, environmentInjector: EnvironmentInjector | null): void โ method RouterOutletContract.activateWith(activatedRoute: ActivatedRoute, environmentInjector: EnvironmentInjector): void - changed:
property Route.redirectTo?: string โ property Route.redirectTo?: string | RedirectFunction - changed:
set RouterLink.routerLink(commands: any[] | string | null | undefined) โ set RouterLink.routerLink(commandsOrUrlTree: any[] | string | UrlTree | null | undefined) - changed:
set RouterLinkWithHref.routerLink(commands: any[] | string | null | undefined) โ set RouterLinkWithHref.routerLink(commandsOrUrlTree: any[] | string | UrlTree | null | undefined) - changed:
type GuardResult = boolean | UrlTree โ type GuardResult = boolean | UrlTree | RedirectCommand - changed:
type QueryParamsHandling = 'merge' | 'preserve' | '' โ type QueryParamsHandling = 'merge' | 'preserve' | 'replace' | '' - changed:
type ResolveFn<T> = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => MaybeAsync<T> โ type ResolveFn<T> = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => MaybeAsync<T | RedirectCommand> - added:
class RedirectCommand - added:
constructor ChildrenOutletContexts(rootInjector: EnvironmentInjector) - added:
constructor OutletContext(rootInjector: EnvironmentInjector) - added:
constructor RedirectCommand(redirectTo: UrlTree, navigationBehaviorOptions?: NavigationBehaviorOptions | undefined) - added:
get OutletContext.injector(): EnvironmentInjector - added:
property RouterConfigOptions.defaultQueryParamsHandling?: QueryParamsHandling - added:
readonly property NavigationBehaviorOptions.browserUrl?: UrlTree | string - added:
readonly property RedirectCommand.navigationBehaviorOptions?: NavigationBehaviorOptions | undefined - added:
readonly property RedirectCommand.redirectTo: UrlTree - added:
set OutletContext.injector(_: EnvironmentInjector) - added:
type RedirectFunction = (redirectData: Pick<ActivatedRouteSnapshot, 'routeConfig' | 'url' | 'params' | 'queryParams' | 'fragment' | 'data' | 'outlet' | 'title'>) => string | UrlTree