Upgrading @angular/router 12 to 13
Breaking12.2.17 → 13.4.0Breaking17Security1Platform6Deprecated12New41Changed14Fixed142Other6
BreakingUpgrade verdict
14 breaking changes and 6 platform requirement changes and a security fix.
In plain terms
- Tests that fake the browser location behave more like real browsers now, so some router tests may need updating.
- Angular Elements no longer declares a wrong peer dependency.
- Code or libraries that still import WrappedValue from Angular core will break and must remove that usage.
- URLs with a question mark inside a query value are now parsed correctly rather than truncated.
Must act Top 5 of 33 that need code or config changes
Node.js requirement changed in 13.0.0-next.13: ^12.14.1 || >=14.0.0 → ^12.20.0 || ^14.15.0 || >=16.10.0.
What you must change
Breaking14
SpyLocation used by RouterTestingModule no longer emits popstate on Location.go, and simulateHashChange now triggers both hashchange and popstate.
SpyLocationRouterTestingModuleLocation.gosimulateHashChangeRouterRemoves the incorrect @angular/platform-browser peer dependency from @angular/elements.
@angular/platform-browserWrappedValue can no longer be imported from @angular/core, which may cause compile or runtime failures in outdated libraries.
WrappedValue@angular/coreThe default url serializer now correctly keeps question marks inside query parameter values instead of dropping everything after them.
routerLink no longer treats null and undefined as empty string, and href is now an attribute binding returning the full native URL.
routerLinkHostBindingDebugElement.propertiesRouterLinkThe router no longer replaces the browser URL when a new navigation cancels an ongoing one.
navigationIdNavigationCancellocation.replaceStateurlChangesSpyLocationRoute.loadChildren no longer accepts a string, and NgModuleFactoryLoader, SystemJsNgModuleFactoryLoader, SpyNgModuleFactoryLoader and DeprecatedLoadChildren are removed.
Route.loadChildrenNgModuleFactoryLoaderSystemJsNgModuleFactoryLoaderSpyNgModuleFactoryLoaderDeprecatedLoadChildrensetupTestingRouterRemoves support for the deprecated WrappedValue.
WrappedValueRemoves the ng-add schematic from @angular/elements.
ng-addRemoves support for the loadChildren string syntax.
loadChildrenRemoves the
ng-add schematic from @angular/elements.ng-addHardens attribute and property binding rules for <iframe> elements, which may require updates to existing iframe usages.
<iframe>SwUpdate#activateUpdate and SwUpdate#checkForUpdate now return Promise<boolean>, which may cause TypeScript type-checking failures.
SwUpdate#activateUpdateSwUpdate#checkForUpdatePromise<boolean>AbstractControl.status is narrowed to FormControlStatus and statusChanges to Observable<FormControlStatus>, which may break comparisons against invalid strings.
FormControlStatusAbstractControl.statusstatusChangesSecurity1
Hardens attribute and property binding rules for <iframe> elements.
<iframe>Platform6
Adds support for TypeScript 4.5.
TypeScript versions older than 4.4.2 are no longer supported.
NodeJS versions older than v12.20.0 are no longer supported due to NodeJS package exports with subpath patterns.
Drops support for TypeScript 4.2 and 4.3.
Adds support for TypeScript 4.4.
Updates the supported Node.js version range to include v16.
Deprecations to plan for
Deprecated12
Deprecates the CachedResourceLoader and RESOURCE_CACHE_PROVIDER symbols, which are no longer needed since Ivy.
CachedResourceLoaderRESOURCE_CACHE_PROVIDERDeprecates the ComponentFactory and ComponentFactoryResolver classes since Ivy makes factory resolution unnecessary.
ComponentFactoryComponentFactoryResolverDeprecates the unused CompilerOptions.useJit and CompilerOptions.missingTranslation config options, which have no effect since Ivy.
CompilerOptions.useJitCompilerOptions.missingTranslationDeprecates the tap operator subscribe signature with separate callback arguments in favor of an observer argument.
tapDeprecates factory-based
downgradeModule calls in favor of NgModule class based calls.downgradeModuleTestRequest no longer accepts ErrorEvent for simulated XHR errors; pass ProgressEvent instead.TestRequestErrorEventProgressEventrenderModuleFactory in @angular/platform-server is deprecated; use renderModule instead.
renderModuleFactoryrenderModule@angular/platform-serverThe SwUpdate#activated observable is deprecated because the return value of SwUpdate#activateUpdate() now indicates the outcome.
SwUpdate#activatedSwUpdate#activateUpdate()The SwUpdate#availalbe observable is deprecated in favor of SwUpdate#versionUpdates and VersionReadyEvent.
SwUpdate#availalbeSwUpdate#versionUpdatesVersionReadyEventDeprecates the ViewEngine-based renderModuleFactory.
renderModuleFactoryDeprecates the SwUpdate#activated observable.
SwUpdate#activatedSwUpdate#activateUpdate()Deprecates the SwUpdate#availalbe observable in favor of SwUpdate#versionUpdates.
SwUpdate#availalbeSwUpdate#versionUpdatesVersionReadyEventAPI changes
Generated by DepDelta from published .d.ts files. Not mixed with prose notes.
- removed:
class ɵangular_packages_router_router_h implements OnDestroy - removed:
class ɵangular_packages_router_router_l - removed:
class ɵangular_packages_router_router_m<T> - removed:
class ɵangular_packages_router_router_n<T> - removed:
class ɵangular_packages_router_router_o implements OnDestroy - removed:
const ɵangular_packages_router_router_a: InjectionToken<void> - removed:
constructor ɵangular_packages_router_router_h(injector: Injector) - removed:
constructor ɵangular_packages_router_router_m(root: ɵangular_packages_router_router_n<T>) - removed:
constructor ɵangular_packages_router_router_n(value: T, children: ɵangular_packages_router_router_n<T>[]) - removed:
constructor ɵangular_packages_router_router_o(router: Router, viewportScroller: ViewportScroller, options?: { scrollPositionRestoration?: 'disabled' | 'enabled' | 'top'; anchorScrolling?: 'disabled' | 'enabled' }) - removed:
function ɵangular_packages_router_router_b(): NgProbeToken - removed:
function ɵangular_packages_router_router_c(router: Router, viewportScroller: ViewportScroller, config: ExtraOptions): ɵangular_packages_router_router_o - removed:
function ɵangular_packages_router_router_d(platformLocationStrategy: PlatformLocation, baseHref: string, options?: ExtraOptions): HashLocationStrategy | PathLocationStrategy - removed:
function ɵangular_packages_router_router_e(router: Router): any - removed:
function ɵangular_packages_router_router_f(urlSerializer: UrlSerializer, contexts: ChildrenOutletContexts, location: Location_2, injector: Injector, loader: NgModuleFactoryLoader, compiler: Compiler, config: Route[][], opts?: ExtraOptions, urlHandlingStrategy?: UrlHandlingStrategy, routeReuseStrategy?: RouteReuseStrategy): Router - removed:
function ɵangular_packages_router_router_g(router: Router): ActivatedRoute - removed:
function ɵangular_packages_router_router_i(r: ɵangular_packages_router_router_h): () => Promise<any> - removed:
function ɵangular_packages_router_router_j(r: ɵangular_packages_router_router_h): (bootstrappedComponentRef: ComponentRef<any>) => void - removed:
function ɵangular_packages_router_router_k(): ReadonlyArray<Provider> - removed:
get ɵangular_packages_router_router_m.root(): T - removed:
method ɵangular_packages_router_router_h.appInitializer(): Promise<any> - removed:
method ɵangular_packages_router_router_h.bootstrapListener(bootstrappedComponentRef: ComponentRef<any>): void - removed:
method ɵangular_packages_router_router_h.ngOnDestroy(): void - removed:
method ɵangular_packages_router_router_n.toString(): string - removed:
method ɵangular_packages_router_router_o.init(): void - removed:
method ɵangular_packages_router_router_o.ngOnDestroy(): void - removed:
property ɵangular_packages_router_router_n.children: ɵangular_packages_router_router_n<T>[] - removed:
property ɵangular_packages_router_router_n.value: T - removed:
readonly property ɵangular_packages_router_router_o.viewportScroller: ViewportScroller - removed:
type DeprecatedLoadChildren = string - changed:
class RouterState extends ɵangular_packages_router_router_m<ActivatedRoute> → class RouterState extends Tree<ActivatedRoute> - changed:
class RouterStateSnapshot extends ɵangular_packages_router_router_m<ActivatedRouteSnapshot> → class RouterStateSnapshot extends Tree<ActivatedRouteSnapshot> - changed:
constructor Router(rootComponentType: Type<any> | null, urlSerializer: UrlSerializer, rootContexts: ChildrenOutletContexts, location: Location_2, injector: Injector, loader: NgModuleFactoryLoader, compiler: Compiler, config: Routes) → constructor Router(rootComponentType: Type<any> | null, urlSerializer: UrlSerializer, rootContexts: ChildrenOutletContexts, location: Location_2, injector: Injector, compiler: Compiler, config: Routes) - changed:
constructor RouterLink(router: Router, route: ActivatedRoute, tabIndex: string, renderer: Renderer2, el: ElementRef) → constructor RouterLink(router: Router, route: ActivatedRoute, tabIndexAttribute: string | null | undefined, renderer: Renderer2, el: ElementRef) - changed:
constructor RouterPreloader(router: Router, moduleLoader: NgModuleFactoryLoader, compiler: Compiler, injector: Injector, preloadingStrategy: PreloadingStrategy) → constructor RouterPreloader(router: Router, compiler: Compiler, injector: Injector, preloadingStrategy: PreloadingStrategy) - changed:
get RouterLink.urlTree(): UrlTree → get RouterLink.urlTree(): UrlTree | null - changed:
get RouterLinkWithHref.urlTree(): UrlTree → get RouterLinkWithHref.urlTree(): UrlTree | null - changed:
property RouterLinkWithHref.href: string → property RouterLinkWithHref.href: string | null - changed:
type Data = { [name: string]: any } → type Data = { [key: string | symbol]: any } - changed:
type LoadChildren = LoadChildrenCallback | DeprecatedLoadChildren → type LoadChildren = LoadChildrenCallback - changed:
type ResolveData = { [name: string]: any } → type ResolveData = { [key: string | symbol]: any } - added:
property ExtraOptions.canceledNavigationResolution?: 'replace' | 'computed' - added:
property Router.canceledNavigationResolution: 'replace' | 'computed' - added:
property RouterOutlet.attachEvents: EventEmitter<unknown> - added:
property RouterOutlet.detachEvents: EventEmitter<unknown> - added:
property RouterOutletContract.attachEvents?: EventEmitter<unknown> - added:
property RouterOutletContract.detachEvents?: EventEmitter<unknown> - added:
readonly property RouterLinkActive.isActiveChange: EventEmitter<boolean> - added:
static property Router.ɵfac: i0.ɵɵFactoryDeclaration<Router, never> - added:
static property Router.ɵprov: i0.ɵɵInjectableDeclaration<Router> - added:
static property RouterLink.ɵdir: i0.ɵɵDirectiveDeclaration<RouterLink, ':not(a):not(area)[routerLink]', never, { 'queryParams': 'queryParams'; 'fragment': 'fragment'; 'queryParamsHandling': 'queryParamsHandling'; 'preserveFragment': 'preserveFragment'; 'skipLocationChange': 'skipLocationChange'; 'replaceUrl': 'replaceUrl'; 'state': 'state'; 'relativeTo': 'relativeTo'; 'routerLink': 'routerLink' }… - added:
static property RouterLink.ɵfac: i0.ɵɵFactoryDeclaration<RouterLink, [null, null, { attribute: 'tabindex' }, null, null]> - added:
static property RouterLinkActive.ɵdir: i0.ɵɵDirectiveDeclaration<RouterLinkActive, '[routerLinkActive]', ['routerLinkActive'], { 'routerLinkActiveOptions': 'routerLinkActiveOptions'; 'routerLinkActive': 'routerLinkActive' }, { 'isActiveChange': 'isActiveChange' }, ['links', 'linksWithHrefs']> - added:
static property RouterLinkActive.ɵfac: i0.ɵɵFactoryDeclaration<RouterLinkActive, [null, null, null, null, { optional: true }, { optional: true }]> - added:
static property RouterLinkWithHref.ɵdir: i0.ɵɵDirectiveDeclaration<RouterLinkWithHref, 'a[routerLink],area[routerLink]', never, { 'target': 'target'; 'queryParams': 'queryParams'; 'fragment': 'fragment'; 'queryParamsHandling': 'queryParamsHandling'; 'preserveFragment': 'preserveFragment'; 'skipLocationChange': 'skipLocationChange'; 'replaceUrl': 'replaceUrl'; 'state': 'state'; 'relativeTo': 'rela… - added:
static property RouterLinkWithHref.ɵfac: i0.ɵɵFactoryDeclaration<RouterLinkWithHref, never> - added:
static property RouterModule.ɵfac: i0.ɵɵFactoryDeclaration<RouterModule, [{ optional: true }, { optional: true }]> - added:
static property RouterModule.ɵinj: i0.ɵɵInjectorDeclaration<RouterModule> - added:
static property RouterModule.ɵmod: i0.ɵɵNgModuleDeclaration<RouterModule, [typeof i1.RouterOutlet, typeof i2.RouterLink, typeof i2.RouterLinkWithHref, typeof i3.RouterLinkActive, typeof i4.ɵEmptyOutletComponent], never, [typeof i1.RouterOutlet, typeof i2.RouterLink, typeof i2.RouterLinkWithHref, typeof i3.RouterLinkActive, typeof i4.ɵEmptyOutletComponent]> - added:
static property RouterOutlet.ɵdir: i0.ɵɵDirectiveDeclaration<RouterOutlet, 'router-outlet', ['outlet'], {}, { 'activateEvents': 'activate'; 'deactivateEvents': 'deactivate'; 'attachEvents': 'attach'; 'detachEvents': 'detach' }, never> - added:
static property RouterOutlet.ɵfac: i0.ɵɵFactoryDeclaration<RouterOutlet, [null, null, null, { attribute: 'name' }, null]> - added:
static property RouterPreloader.ɵfac: i0.ɵɵFactoryDeclaration<RouterPreloader, never> - added:
static property RouterPreloader.ɵprov: i0.ɵɵInjectableDeclaration<RouterPreloader> - added:
static property ɵEmptyOutletComponent.ɵcmp: i0.ɵɵComponentDeclaration<ɵEmptyOutletComponent, 'ng-component', never, {}, {}, never, never> - added:
static property ɵEmptyOutletComponent.ɵfac: i0.ɵɵFactoryDeclaration<ɵEmptyOutletComponent, never> - added:
type ɵRestoredState = { [k: string]: any; navigationId: number; ɵrouterPageId?: number }
- removed:
export * from './testing/testing'
- removed:
class SpyNgModuleFactoryLoader implements NgModuleFactoryLoader - removed:
constructor SpyNgModuleFactoryLoader(compiler: Compiler) - removed:
function setupTestingRouter(urlSerializer: UrlSerializer, contexts: ChildrenOutletContexts, location: Location_2, loader: NgModuleFactoryLoader, compiler: Compiler, injector: Injector, routes: Route[][], urlHandlingStrategy?: UrlHandlingStrategy): Router - removed:
get SpyNgModuleFactoryLoader.stubbedModules(): { [path: string]: any } - removed:
method SpyNgModuleFactoryLoader.load(path: string): Promise<NgModuleFactory<any>> - removed:
set SpyNgModuleFactoryLoader.stubbedModules(modules: { [path: string]: any }) - changed:
function setupTestingRouter(urlSerializer: UrlSerializer, contexts: ChildrenOutletContexts, location: Location_2, loader: NgModuleFactoryLoader, compiler: Compiler, injector: Injector, routes: Route[][], opts?: ExtraOptions, urlHandlingStrategy?: UrlHandlingStrategy): Router → function setupTestingRouter(urlSerializer: UrlSerializer, contexts: ChildrenOutletContexts, location: Location_2, compiler: Compiler, injector: Injector, routes: Route[][], opts?: ExtraOptions | UrlHandlingStrategy, urlHandlingStrategy?: UrlHandlingStrategy, routeReuseStrategy?: RouteReuseStrategy): Router - added:
static property RouterTestingModule.ɵfac: i0.ɵɵFactoryDeclaration<RouterTestingModule, never> - added:
static property RouterTestingModule.ɵinj: i0.ɵɵInjectorDeclaration<RouterTestingModule> - added:
static property RouterTestingModule.ɵmod: i0.ɵɵNgModuleDeclaration<RouterTestingModule, never, never, [typeof i1.RouterModule]>
- removed:
export * from './upgrade/upgrade'