Skip to content

Upgrading @angular/router 21 to 22

Breaking21.2.25 → 22.2.4Breaking26Security33Platform3Deprecated7New84Changed29Fixed366Other5

Fetching 57 releases from GitHub…56 / 57
BreakingUpgrade verdict

23 breaking changes and 3 platform requirement changes and 33 security fixes.

  • Templates relying on old shadow DOM selector syntax will no longer work.
  • Apps depending on the old shadow CSS polyfills must migrate to supported encapsulation.
  • Renames `TestBed.getFixture` to `TestBed.getLastFixture` and updates the implementation.
  • Removes checkNoChanges from the public API.
Top 5 of 66 that need code or config changes

Node.js requirement changed in 22.0.0-rc.2: ^20.19.0 || ^22.12.0 || >=24.0.0 → ^22.22.3 || ^24.15.0 || >=26.0.0.

Breaking23
Removes dedicated support for legacy shadow DOM selectors.
Removes deprecated shadow CSS encapsulation polyfills.
Renames TestBed.getFixture to TestBed.getLastFixture and updates the implementation.
TestBed.getFixtureTestBed.getLastFixture
Removes checkNoChanges from the public API.
checkNoChanges
Removes createNgModuleRef.
createNgModuleRef
Removes ComponentFactoryResolver and ComponentFactory from the API surface.
ComponentFactoryResolverComponentFactory
Removes string support from min and max validation rules.
minmax
Removes the Hammer integration.
Hammer
Removes the deprecated provideRoutes function.
provideRoutes
Deprecated getAngularLib/setAngularLib are removed; use getAngularJSGlobal/setAngularJSGlobal instead.
getAngularLibsetAngularLibgetAngularJSGlobalsetAngularJSGlobal
paramsInheritanceStrategy now defaults to 'always' instead of 'emptyOnly', so route parameters are inherited from all parent routes.
paramsInheritanceStrategy
provideRoutes() is removed; use provideRouter() or the ROUTES multi token instead.
provideRoutes()provideRouter()ROUTES
Removes string value support from the min and max validation rules; bound values must be numbers or null.
minmax
The second argument of appRef.bootstrap no longer accepts any; the element passed must not be nullable.
ApplicationRef.bootstrap
Removes styles when they appear no longer used by an associated host, which may leave other DOM unstyled.
ViewEncapsulation.Emulated
Removes Hammer integration.
Hammer
Removes createNgModuleRef; use createNgModule instead.
createNgModuleRefcreateNgModule
Uses FetchBackend as the default HttpBackend implementation.
FetchBackendHttpBackend
The return type of TitleStrategy.getResolvedTitleForRoute now reflects that it returns only string or undefined.
TitleStrategy.getResolvedTitleForRoute
The currentSnapshot parameter in CanMatchFn and the canMatch method of CanMatch is now required.
CanMatchFnCanMatchcanMatchcurrentSnapshot
Disables the nullishCoalescingNotNullable and optionalChainNotNullable diagnostics on ng update, which now trigger on existing projects.
nullishCoalescingNotNullableoptionalChainNotNullable
Elements with multiple matching selectors now throw at compile time.
Reverts support for nested animations in core.
Security33
Hardens param encoding against prototype pollution.
Hardens JIT against prototype pollution.
Blocks dangerous data: and vbscript: URLs in the URL sanitizer.
Extends the data: URL allowlist for non-executable MIME types.
@angular/router: Denial of Service via Unmatched Empty-Path Outlet Route Matching in Server-Side Rendering (SSR)
High
@angular/router: Denial of Service via RouterLink Query Parameter Retention in Server-Side Rendering (SSR)
High
Angular Server-Side Rendering (SSR): Denial of Service via Numeric URL Matrix Parameters
High
Rejects prefixed SVG script hosts.
Prevents TransferState prototype pollution.
TransferState
Disallows event handler attributes in Meta.
Meta
Rejects prefixed SVG script hosts.
Hardens platform location origin validation during SSR.
Prevents ReDoS in SOURCEMAP_URL_REGEXP in platform-browser.
SOURCEMAP_URL_REGEXP
Guards against DOM clobbering in declareExperimentalWebMcpTool.
declareExperimentalWebMcpTool
Treats iframe credentialless as security-sensitive.
Prevents prototype pollution in formatDateTime.
formatDateTime
Uses cryptographically secure SHA-256 for transfer cache key generation.
Sanitizes href and xlink:href attributes of any element in the MathML namespace.
hrefxlink:href
Sanitizes two-way properties.
Hardens TransferState restoration against DOM clobbering.
TransferState
Hardens FormGroup control lookups against prototype shadowing.
FormGroup
Hardens platform location origin validation during SSR.
Strips sensitive headers on cross-origin redirects in service-worker.
Sanitizes dynamic href and xlink:href bindings on SVG a elements.
hrefxlink:href
Uses Object.create(null) for LOCALE_DATA as a hardening measure.
LOCALE_DATA
Throws on suspicious URLs and restricts protocol-relative URLs in platform-server.
Prevents SSRF bypasses via backslash URLs in HttpClient.
HttpClient
Secures location and document initialization against SSRF and path hijack.
Validates security-sensitive attributes in i18n bindings.
Prevents SSRF bypasses via protocol-relative and backslash URLs.
Validates the locale in getOutputPathFn to prevent path traversal.
getOutputPathFn
Sanitizes translated form attributes in core.
Sanitizes translated attribute bindings with interpolations.
Platform3
Adds support for Node.js 26.0.0.
Drops support for TypeScript 5.9.
Drops Node.js v20 support; minimum supported Node.js versions are now v22.22.0 and v24.13.1.
Deprecated7
Deprecates JSONP support.
jsonp
Deprecates HttpClient.jsonp, HttpClientJsonpModule, and related JSONP classes and functions in favor of standard HTTP requests.
HttpClient.jsonpHttpClientJsonpModule
Deprecates JSONP support in HttpClient.
HttpClient.jsonpHttpClientJsonpModule
Deprecates ServerXhr in @angular/platform-server.
ServerXhr
Deprecates XHR support in @angular/platform-server in favor of standard fetch APIs.
@angular/platform-server
withFetch is now deprecated and can be safely removed.
withFetch
The reportProgress option is deprecated; use reportUploadProgress and reportDownloadProgress instead.
reportProgressreportUploadProgressreportDownloadProgress

Generated by DepDelta from published .d.ts files. Not mixed with prose notes.

  • removed: interface DefaultExport<T>
  • removed: property DefaultExport.default: T
  • changed: class RedirectCommand → class RedirectCommand extends Error
  • changed: method CanMatch.canMatch(route: Route, segments: UrlSegment[], currentSnapshot?: PartialMatchRouteSnapshot): MaybeAsync<GuardResult> → method CanMatch.canMatch(route: Route, segments: UrlSegment[], currentSnapshot: PartialMatchRouteSnapshot): MaybeAsync<GuardResult>
  • changed: property ExtraOptions.bindToComponentInputs?: boolean → property ExtraOptions.bindToComponentInputs?: boolean | ComponentInputBindingOptions
  • changed: property RouterLinkActive.routerLinkActiveOptions: { exact: boolean } | Partial<IsActiveMatchOptions> → property RouterLinkActive.routerLinkActiveOptions: { exact: boolean } | Partial<IsActiveMatchOptions> | null | undefined
  • changed: set RouterLinkActive.routerLinkActive(data: string[] | string) → set RouterLinkActive.routerLinkActive(data: string[] | string | null | undefined)
  • changed: static property RouteReuseStrategy.ɵprov: i0.ɵɵInjectableDeclaration<RouteReuseStrategy> → static property RouteReuseStrategy.ɵprov: i0.ɵɵInjectableDeclaration<any>
  • changed: static property Router.ɵprov: i0.ɵɵInjectableDeclaration<Router> → static property Router.ɵprov: i0.ɵɵInjectableDeclaration<any>
  • changed: static property UrlSerializer.ɵprov: i0.ɵɵInjectableDeclaration<UrlSerializer> → static property UrlSerializer.ɵprov: i0.ɵɵInjectableDeclaration<any>
  • changed: type CanMatchFn = (route: Route, segments: UrlSegment[], currentSnapshot?: PartialMatchRouteSnapshot) => MaybeAsync<GuardResult> → type CanMatchFn = (route: Route, segments: UrlSegment[], currentSnapshot: PartialMatchRouteSnapshot) => MaybeAsync<GuardResult>
  • added: function containsTree(container: UrlTree, containee: UrlTree, options?: Partial<IsActiveMatchOptions>): boolean
  • added: interface ComponentInputBindingOptions
  • added: interface ResourceContext
  • added: method RouteReuseStrategy.retrieveStoredRouteHandles?(): Array<DetachedRouteHandle>
  • added: method RouteReuseStrategy.shouldDestroyInjector?(route: Route): boolean
  • added: property ActivatedRoute.resources?: ResourceResult
  • added: property ActivatedRouteSnapshot.resources?: ResourceResult
  • added: property ComponentInputBindingOptions.queryParams?: boolean
  • added: property ComponentInputBindingOptions.unmatchedInputBehavior?: 'alwaysUndefined' | 'undefinedIfStale'
  • added: property ResourceContext.data: Signal<Record<string, any>>
  • added: property ResourceContext.fragment: Signal<string | null>
  • added: property ResourceContext.params: Signal<Params>
  • added: property ResourceContext.queryParams: Signal<Params>
  • added: property Route.resources?: (ctx: ResourceContext) => ResourceResult | Promise<ResourceResult>
  • added: property RouterLink.browserUrl: i0.InputSignal<string | UrlTree | undefined>
  • added: type ResourceResult = Record<string, Resource<unknown> & Pick<WritableResource<unknown>, 'reload'>>
  • removed: export { DefaultExport } from './_router_module-chunk'
  • removed: function provideRoutes(routes: Routes): Provider[]
  • changed: function withComponentInputBinding(): ComponentInputBindingFeature → function withComponentInputBinding(options?: ComponentInputBindingOptions): ComponentInputBindingFeature
  • changed: function withExperimentalAutoCleanupInjectors(): ExperimentalAutoCleanupInjectorsFeature → function withExperimentalAutoCleanupInjectors(): AutoCleanupInjectorsFeature
  • changed: method TitleStrategy.getResolvedTitleForRoute(snapshot: ActivatedRouteSnapshot): any → method TitleStrategy.getResolvedTitleForRoute(snapshot: ActivatedRouteSnapshot): string | undefined
  • changed: static property ChildrenOutletContexts.ɵprov: i0.ɵɵInjectableDeclaration<ChildrenOutletContexts> → static property ChildrenOutletContexts.ɵprov: i0.ɵɵInjectableDeclaration<any>
  • changed: static property DefaultTitleStrategy.ɵprov: i0.ɵɵInjectableDeclaration<DefaultTitleStrategy> → static property DefaultTitleStrategy.ɵprov: i0.ɵɵInjectableDeclaration<any>
  • changed: static property NoPreloading.ɵprov: i0.ɵɵInjectableDeclaration<NoPreloading> → static property NoPreloading.ɵprov: i0.ɵɵInjectableDeclaration<any>
  • changed: static property PreloadAllModules.ɵprov: i0.ɵɵInjectableDeclaration<PreloadAllModules> → static property PreloadAllModules.ɵprov: i0.ɵɵInjectableDeclaration<any>
  • changed: static property RouterPreloader.ɵprov: i0.ɵɵInjectableDeclaration<RouterPreloader> → static property RouterPreloader.ɵprov: i0.ɵɵInjectableDeclaration<any>
  • changed: static property TitleStrategy.ɵprov: i0.ɵɵInjectableDeclaration<TitleStrategy> → static property TitleStrategy.ɵprov: i0.ɵɵInjectableDeclaration<any>
  • changed: static property UrlHandlingStrategy.ɵprov: i0.ɵɵInjectableDeclaration<UrlHandlingStrategy> → static property UrlHandlingStrategy.ɵprov: i0.ɵɵInjectableDeclaration<any>
  • added: export { ComponentInputBindingOptions }
  • added: export { DefaultExport } from '@angular/core'
  • added: export { ResourceContext } from './_router_module-chunk'
  • added: export { ResourceResult } from './_router_module-chunk'
  • added: export { containsTree } from './_router_module-chunk'
  • added: function nonBlocking<T, R extends Resource<T>>(res: R): R
  • added: function withAutoCleanupInjectors(): AutoCleanupInjectorsFeature
  • added: function withRouterResources(): RouterResourcesFeature
  • added: type AutoCleanupInjectorsFeature = RouterFeature<RouterFeatureKind.AutoCleanupInjectorsFeature>
  • added: type RouterResourcesFeature = RouterFeature<RouterFeatureKind.RouterResourcesFeature>