Upgrading @angular/router 15 to 16
Breaking15.2.10 → 16.2.12Breaking38Security1Platform5Deprecated8New45Changed6Fixed152Other3
BreakingUpgrade verdict
35 breaking changes and 4 platform requirement changes and a security fix.
In plain terms
- The tool that made older libraries built for the old compiler work with newer Angular is gone.
- Removes the deprecated EventManager method addGlobalEventListener.
- Removes the deprecated XhrFactory export from the http entrypoint.
- Code that read the factories property on IterableDiffers will no longer compile or work.
Must act Top 5 of 48 that need code or config changes
Node.js requirement changed in 16.0.0-rc.0: ^14.20.0 || ^16.13.0 || >=18.10.0 → ^16.14.0 || >=18.10.0.
What you must change
Breaking35
Removes the Angular Compatibility Compiler (ngcc).
ngccRemoves the deprecated EventManager method addGlobalEventListener.
EventManageraddGlobalEventListenerRemoves the deprecated XhrFactory export from the http entrypoint.
XhrFactoryDrops the public
factories property for IterableDiffers.IterableDiffersfactoriesDrops support for
zone.js versions <=0.12.0.zone.jsRemoves
entryComponents.entryComponentsRemoves the ReflectiveInjector symbol.
ReflectiveInjectorAdds a migration to remove
Router guard and resolver interfaces.RouterRemoves the deprecated
BrowserTransferStateModule symbol.BrowserTransferStateModuleRenames
provideServerSupport to provideServerRendering.provideServerSupportprovideServerRenderingRemoves the
renderApplication overload that accepts a component.renderApplicationRemoves the deprecated
renderModuleFactory.renderModuleFactoryRemoves deprecated ComponentFactoryResolver from APIs.
ComponentFactoryResolverRemoves RouterEvent from the Event union type.
RouterEventEventRemoves Angular Compatibility Compiler (ngcc), so Angular View Engine libraries no longer work.
ngccChanges Angular Package Format: removes FESM2015, replaces ES2020 with ES2022 and FESM2020 with FESM2022.
FESM2015ES2020ES2022FESM2020FESM2022Removes deprecated XhrFactory export from @angular/common/http; use the one from @angular/common.
XhrFactoryDeletes entryComponents from @NgModule and @Component and removes ANALYZE_FOR_ENTRY_COMPONENTS token.
entryComponents@NgModule@ComponentANALYZE_FOR_ENTRY_COMPONENTSRemoves ComponentFactoryResolver from Router APIs; use ViewContainerRef.createComponent without a factory resolver.
ComponentFactoryResolverViewContainerRef.createComponentRemoves the ReflectiveInjector and related symbols; use Injector.create to create an injector instead.
ReflectiveInjectorInjector.createRemoves the deprecated BrowserTransferStateModule; TransferState can be injected without providing the module.
BrowserTransferStateModuleTransferStateRemoves the ReflectiveInjector symbol.
ReflectiveInjectorrenderApplication no longer accepts a root component as its first argument; pass a bootstrapping function returning Promise<ApplicationRef> instead.renderApplicationApplicationRefbootstrapApplicationThe
APP_ID token value is no longer randomly generated; bootstrapping multiple applications on one page now requires providing APP_ID yourself.APP_IDbootstrapApplicationRemoves
renderModuleFactory; use renderModule instead.renderModuleFactoryrenderModuleRemoves Node.js v14 support; Node.js v16 and v18 remain officially supported.
Removes Node.js v14 support.
RendererType2.styles no longer accepts nested arrays.
RendererType2.stylesProvides MockPlatformLocation by default in tests, which may break tests relying on BrowserPlatformLocation.
MockPlatformLocationBrowserPlatformLocationPlatformLocationLocation.getState()TestBed.configureTestingModuleMakes ngTemplateOutletContext mismatches a compile-time error.
ngTemplateOutletContextNgTemplateOutletTemplateRefQueryList.filter now narrows types with type guard functions, which may require application code updates.
QueryList.filterThe Scroll event's routerEvent property may now also be a NavigationSkipped event, not only NavigationEnd.
ScrollrouterEventNavigationSkippedNavigationEndUsers using SSR with JIT mode must now add
import to @angular/compiler before bootstrapping the application.@angular/compilerComponentRef.setInput only sets the input when the new value differs from the previous one based on Object.is equality.
ComponentRef.setInputObject.isRouter.createUrlTree now handles more scenarios correctly, which may change behavior of tests with invalid ActivatedRoute mocks.
ActivatedRouteRouter.createUrlTreerouter.navigateSecurity1
Changes URL sanitization to only block javascript: URLs.
Platform4
Adds support for TypeScript 5.1.
Adds support for TypeScript 5.1.
Drops support for TypeScript 4.8.
Removes Node.js v14 support.
Deprecations to plan for
Deprecated8
Introduces
runInInjectionContext and deprecates the prior version.runInInjectionContextDeprecates the
moduleId @Component property.moduleId@ComponentDeprecates the
withServerTransition call.withServerTransitionDeprecates
useAbsoluteUrl and baseUrl.useAbsoluteUrlbaseUrlmakeStateKey, StateKey and TransferState move from @angular/platform-browser to @angular/core.
makeStateKeyStateKeyTransferStateDeprecates the @Directive/@Component moduleId property, which will be removed in v17.
moduleId@Directive@ComponentDeprecates the platform-server PlatformConfig.baseUrl and PlatformConfig.useAbsoluteUrl options as unused.
PlatformConfig.baseUrlPlatformConfig.useAbsoluteUrlApplicationConfig has moved; import it from @angular/core instead.ApplicationConfig@angular/coreAPI changes
Generated by DepDelta from published .d.ts files. Not mixed with prose notes.
- removed:
function ɵflatten<T>(arr: T[][]): T[] - removed:
function ɵwithPreloading(preloadingStrategy: Type<PreloadingStrategy>): PreloadingFeature - removed:
get RouterLink.preserveFragment(): boolean - removed:
get RouterLink.replaceUrl(): boolean - removed:
get RouterLink.skipLocationChange(): boolean - removed:
get RouterLinkWithHref.preserveFragment(): boolean - removed:
get RouterLinkWithHref.replaceUrl(): boolean - removed:
get RouterLinkWithHref.skipLocationChange(): boolean - removed:
method RouterOutletContract.activateWith(activatedRoute: ActivatedRoute, resolver: ComponentFactoryResolver | null): void - removed:
property OutletContext.resolver: ComponentFactoryResolver | null - removed:
set RouterLink.preserveFragment(preserveFragment: boolean | string | null | undefined) - removed:
set RouterLink.replaceUrl(replaceUrl: boolean | string | null | undefined) - removed:
set RouterLink.skipLocationChange(skipLocationChange: boolean | string | null | undefined) - removed:
set RouterLinkWithHref.preserveFragment(preserveFragment: boolean | string | null | undefined) - removed:
set RouterLinkWithHref.replaceUrl(replaceUrl: boolean | string | null | undefined) - removed:
set RouterLinkWithHref.skipLocationChange(skipLocationChange: boolean | string | null | undefined) - changed:
constructor Scroll(routerEvent: NavigationEnd, position: [number, number] | null, anchor: string | null) → constructor Scroll(routerEvent: NavigationEnd | NavigationSkipped, position: [number, number] | null, anchor: string | null) - changed:
function ɵafterNextNavigation(router: Router, action: () => void): void → function ɵafterNextNavigation(router: { events: Observable<Event_2> }, action: () => void): void - changed:
method RouterOutlet.activateWith(activatedRoute: ActivatedRoute, resolverOrInjector?: ComponentFactoryResolver | EnvironmentInjector | null): void → method RouterOutlet.activateWith(activatedRoute: ActivatedRoute, environmentInjector?: EnvironmentInjector | null): void - changed:
readonly property Scroll.routerEvent: NavigationEnd → readonly property Scroll.routerEvent: NavigationEnd | NavigationSkipped - changed:
static property RouterLink.ɵdir: i0.ɵɵDirectiveDeclaration<RouterLink, '[routerLink]', never, { 'target': 'target'; 'queryParams': 'queryParams'; 'fragment': 'fragment'; 'queryParamsHandling': 'queryParamsHandling'; 'state': 'state'; 'relativeTo': 'relativeTo'; 'preserveFragment': 'preserveFragment'; 'skipLocationChange': 'skipLocationChange'; 'replaceUrl': 'replaceUrl'; 'routerLink': 'routerLink… → static property RouterLink.ɵdir: i0.ɵɵDirectiveDeclaration<RouterLink, '[routerLink]', never, { 'target': { 'alias': 'target'; 'required': false }; 'queryParams': { 'alias': 'queryParams'; 'required': false }; 'fragment': { 'alias': 'fragment'; 'required': false }; 'queryParamsHandling': { 'alias': 'queryParamsHandling'; 'required': false }; 'state': { 'alias': 'state'; 'required': false }; 'rela… - changed:
static property RouterLinkActive.ɵdir: i0.ɵɵDirectiveDeclaration<RouterLinkActive, '[routerLinkActive]', ['routerLinkActive'], { 'routerLinkActiveOptions': 'routerLinkActiveOptions'; 'ariaCurrentWhenActive': 'ariaCurrentWhenActive'; 'routerLinkActive': 'routerLinkActive' }, { 'isActiveChange': 'isActiveChange' }, ['links'], never, true, never> → static property RouterLinkActive.ɵdir: i0.ɵɵDirectiveDeclaration<RouterLinkActive, '[routerLinkActive]', ['routerLinkActive'], { 'routerLinkActiveOptions': { 'alias': 'routerLinkActiveOptions'; 'required': false }; 'ariaCurrentWhenActive': { 'alias': 'ariaCurrentWhenActive'; 'required': false }; 'routerLinkActive': { 'alias': 'routerLinkActive'; 'required': false } }, { 'isActiveChange': 'isActiv… - changed:
static property RouterLinkWithHref.ɵdir: i0.ɵɵDirectiveDeclaration<RouterLink, '[routerLink]', never, { 'target': 'target'; 'queryParams': 'queryParams'; 'fragment': 'fragment'; 'queryParamsHandling': 'queryParamsHandling'; 'state': 'state'; 'relativeTo': 'relativeTo'; 'preserveFragment': 'preserveFragment'; 'skipLocationChange': 'skipLocationChange'; 'replaceUrl': 'replaceUrl'; 'routerLink': 'ro… → static property RouterLinkWithHref.ɵdir: i0.ɵɵDirectiveDeclaration<RouterLink, '[routerLink]', never, { 'target': { 'alias': 'target'; 'required': false }; 'queryParams': { 'alias': 'queryParams'; 'required': false }; 'fragment': { 'alias': 'fragment'; 'required': false }; 'queryParamsHandling': { 'alias': 'queryParamsHandling'; 'required': false }; 'state': { 'alias': 'state'; 'required': false… - changed:
static property RouterOutlet.ɵdir: i0.ɵɵDirectiveDeclaration<RouterOutlet, 'router-outlet', ['outlet'], { 'name': 'name' }, { 'activateEvents': 'activate'; 'deactivateEvents': 'deactivate'; 'attachEvents': 'attach'; 'detachEvents': 'detach' }, never, never, true, never> → static property RouterOutlet.ɵdir: i0.ɵɵDirectiveDeclaration<RouterOutlet, 'router-outlet', ['outlet'], { 'name': { 'alias': 'name'; 'required': false } }, { 'activateEvents': 'activate'; 'deactivateEvents': 'deactivate'; 'attachEvents': 'attach'; 'detachEvents': 'detach' }, never, never, true, never> - changed:
type Event = RouterEvent | NavigationStart | NavigationEnd | NavigationCancel | NavigationError | RoutesRecognized | GuardsCheckStart | GuardsCheckEnd | RouteConfigLoadStar… → type Event = NavigationStart | NavigationEnd | NavigationCancel | NavigationError | RoutesRecognized | GuardsCheckStart | GuardsCheckEnd | RouteConfigLoadStart | RouteConfi… - changed:
type RouterFeatures = PreloadingFeature | DebugTracingFeature | InitialNavigationFeature | InMemoryScrollingFeature | RouterConfigurationFeature | NavigationErrorHandlerFeature → type RouterFeatures = PreloadingFeature | DebugTracingFeature | InitialNavigationFeature | InMemoryScrollingFeature | RouterConfigurationFeature | NavigationErrorHandlerFeature | Co… - added:
function mapToCanActivate(providers: Array<Type<{ canActivate: CanActivateFn }>>): CanActivateFn[] - added:
function mapToCanActivateChild(providers: Array<Type<{ canActivateChild: CanActivateChildFn }>>): CanActivateChildFn[] - added:
function mapToCanDeactivate<T = unknown>(providers: Array<Type<{ canDeactivate: CanDeactivateFn<T> }>>): CanDeactivateFn<T>[] - added:
function mapToCanMatch(providers: Array<Type<{ canMatch: CanMatchFn }>>): CanMatchFn[] - added:
function mapToResolve<T>(provider: Type<{ resolve: ResolveFn<T> }>): ResolveFn<T> - added:
function withComponentInputBinding(): ComponentInputBindingFeature - added:
function ɵloadChildren(route: Route, compiler: Compiler, parentInjector: Injector, onLoadEndListener?: (r: Route) => void): Observable<LoadedRouterConfig> - added:
get Router.lastSuccessfulNavigation(): Navigation | null - added:
property ExtraOptions.bindToComponentInputs?: boolean - added:
property RouterLink.preserveFragment: boolean - added:
property RouterLink.replaceUrl: boolean - added:
property RouterLink.skipLocationChange: boolean - added:
property RouterLinkWithHref.preserveFragment: boolean - added:
property RouterLinkWithHref.replaceUrl: boolean - added:
property RouterLinkWithHref.skipLocationChange: boolean - added:
readonly property Router.componentInputBindingEnabled: boolean - added:
readonly property RouterOutlet.supportsBindingToComponentInputs = true - added:
readonly property RouterOutletContract.supportsBindingToComponentInputs?: true - added:
static property RouterLink.ngAcceptInputType_preserveFragment: unknown - added:
static property RouterLink.ngAcceptInputType_replaceUrl: unknown - added:
static property RouterLink.ngAcceptInputType_skipLocationChange: unknown - added:
static property RouterLinkWithHref.ngAcceptInputType_preserveFragment: unknown - added:
static property RouterLinkWithHref.ngAcceptInputType_replaceUrl: unknown - added:
static property RouterLinkWithHref.ngAcceptInputType_skipLocationChange: unknown
- added:
readonly property RouterTestingHarness.fixture: ComponentFixture<unknown>