Upgrading @angular/platform-browser 18 to 19
Breaking18.2.14 → 19.2.25Breaking101Security18Platform5New39Changed11Fixed228Other4
SecurityThrows on suspicious URLs and restricts protocol-relative URLs in platform-server.e2fb854d55 ↗
BreakingUpgrade verdict
93 breaking changes and 5 platform requirement changes and 18 security fixes.
In plain terms
- If a translation adds an attribute Angular does not recognize, it will no longer appear in the rendered output.
- On the server, apps must now pass a context object when starting up instead of relying on a shared global platform.
- In templates, writing `this.` before a name now reads a component property instead of a template variable.
- New components, directives and pipes no longer need to be declared in an NgModule unless you opt out.
Must act Top 5 of 116 that need code or config changes
What you must change
Breaking93
Angular now only applies known HTML attributes from translated ICU content; unknown attributes are dropped and not rendered.
Server bootstrapping no longer relies on a global platform injector; bootstrapApplication now takes a BootstrapContext.
BootstrapContextbootstrapApplicationgetPlatform()destroyPlatform()this.foo property reads no longer refer to template context variables.Angular directives, components and pipes are now standalone by default.
ExperimentalPendingTasks has been renamed to PendingTasks.ExperimentalPendingTasksPendingTaskscreateComponent now renders default fallback content with empty projectableNodes.createComponentprojectableNodesng-contentThe deprecated
factories property in KeyValueDiffers has been removed.KeyValueDiffersfactoriesThe
name option in the ng add @localize schematic has been removed in favor of the project option.nameprojectThe deprecated
BrowserModule.withServerTransition method has been removed.BrowserModule.withServerTransitionAPP_IDThe
Router.errorHandler property has been removed.Router.errorHandlerwithNavigationErrorHandlerprovideRouterRouterModule.forRootresolveNavigationPromiseOnErrorDisables standalone by default on older versions of Angular.
Flips the default value for
standalone to true.standaloneTreats directives, pipes and components as standalone by default.
Falls back to default ng-content when projectable nodes are empty.
ng-contentElements switch to ComponentRef.setInput and remove custom scheduler.
ComponentRef.setInputRemoves the deprecated name option from localize.
nameRemoves complete calls for migrated outputs.
Flips the default standalone flag in the route-lazy-loading migration.
Includes the output migration in the defaults of the signal migration.
Removes the deprecated
BrowserModule.withServerTransition method.BrowserModule.withServerTransitionRemoves the setter for
injector on OutletContext.OutletContextinjectorRemoves the deprecated BrowserModule.withServerTransition method.
BrowserModule.withServerTransitionAPP_IDRenders default fallback content when projectableNodes is an empty array in createComponent.
createComponentprojectableNodesng-contentdocument.createTextNodeFixes :host parsing in pseudo-selectors.
:hostMakes this.a always refer to class property a.
this.aTiming changes for the
effect API in developer preview.effectDoes not migrate next calls in templates if not an EventEmitter.
EventEmitternextEffects triggered outside change detection now run as part of change detection instead of as a microtask.
Effects triggered during change detection now run earlier, before the component's template.
Errors thrown during
ApplicationRef.tick are now rethrown when using TestBed.ApplicationRef.tickTestBedComponentFixture.whenStablerethrowApplicationErrorsTestBed.configureTestingModuleZone coalescing and hybrid mode scheduling timers now run in the zone above Angular rather than the root zone.
fakeAsynctickflushRe-assigns error codes to be within core bounds (<1000).
Sets encapsulation to None for empty component styles.
Change detection timing around custom elements has changed subtly.
Properly resolves tsconfig paths on Windows.
Updates the
Resolve interface to include RedirectCommand like ResolveFn.ResolveRedirectCommandResolveFnAdds a compiler diagnostic for unused standalone imports.
Adds support for the typeof keyword in template expressions.
typeofAdds a more specific matcher for the hydrate never block.
Avoids having to duplicate the core environment.
Fixes incorrect projection of control flow nodes with root at the end.
Fixes multiline selectors.
Handles typeof expressions in the serializer.
typeofIgnores placeholder-only i18n messages.
Resolves :host:host-context(.foo).
:host:host-context(.foo)Transforms chained pseudo-selectors.
Adds a strictStandalone flag that enforces standalone.
strictStandaloneEnsures template style elements are preprocessed as inline styles.
Generates the HMR replacement module.
Does not fail fatally when references to a non-existent module are discovered.
Does not report unused declarations coming from an imported array.
Fixes incorrectly generating relative file paths on case-insensitive platforms.
Makes the unused imports diagnostic easier to read.
Reports individual diagnostics for unused imports.
Changes
effect() execution timing and makes allowSignalWrites a no-op.effect()allowSignalWritesCleans up the event contract once hydration is done.
ComponentFixture autoDetect feature now works like production.
ComponentFixtureEnsures the ViewContext is retained after closure minification.
ViewContextFixes issues with control flow and incremental hydration.
Prevents errors on contract cleanup.
Prevents trying to trigger incremental hydration on CSR.
Resolves forward-referenced host directives during directive matching.
Schedulers run in zone above Angular rather than root.
Elements support output()-shaped outputs.
output()Adds ability to clear a FormRecord.
FormRecordFixes FormRecord type inference.
FormRecordPromotes withRequestsMadeViaParent to stable.
withRequestsMadeViaParentPreserves all headers from Headers object.
HeadersAdds a combined migration for all signals APIs.
Adds a schematic to migrate to signal queries.
Captures output migration stats.
Exposes output as function migration.
Introduces the signal input migration as an
ng generate schematic.ng generatePrints output migration stats in ng generate.
ng generateReplaces .next usage on outputs.
Adds outputs migration to the combined shorthand.
Changes imports to be G3 compatible.
Makes the inject migration always insert generated variables before the super call.
Fixes the inject migration not inserting generated code after super call in some cases.
Migrates more .next output usages.
Properly bundles shared compiler code into migrations.
Properly handles comments in the output migration.
Properly migrates output aliases.
Properly replaces imports across files.
Replaces removed NgModules in tests with their exports.
NgModuleAdds a
routerOutletData input to the RouterOutlet directive.RouterOutletrouterOutletDataAligns the
RouterModule.forRoot error handler with the provider error handler.RouterModule.forRootAllows specifying
maxAge for the entire application in the service worker.maxAgeFinishes the implementation of the service worker
refreshAhead feature.refreshAheadErrors thrown during ApplicationRef.tick are now rethrown when using TestBed.
ApplicationRef.tickTestBedComponentFixture.whenStablerethrowApplicationErrorsTestBed.configureTestingModuleComponentFixture autoDetect now attaches the fixture to ApplicationRef, reporting errors to ErrorHandler.ComponentFixtureApplicationRefErrorHandlerFixes fixture.detectChanges with autoDetect disabled and zoneless.
fixture.detectChangesMigrates .pipe calls in outputs used in tests.
Security18
Throws on suspicious URLs and restricts protocol-relative URLs in platform-server.
Sanitizes placeholder values.
Sanitizes dynamic href and xlink:href bindings on SVG a elements.
hrefxlink:hrefStrips namespaced SVG script elements during template compilation.
Rejects script element as a dynamic component host.
Sanitizes meta selectors.
Synchronizes core sanitization schema with compiler.
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 in platform-server.
Disallows translations of iframe src attributes in the compiler.
iframesrcSanitizes translated attribute bindings that contain interpolations.
Sanitizes translated form attributes.
Blocks creation of sensitive URI attributes from ICU messages.
Sanitizes sensitive attributes on SVG script elements.
Prevents XSS via SVG animation attributeName and MathML/SVG URLs in the compiler.
attributeNamePrevents XSRF token leakage to protocol-relative URLs.
Addresses Trusted Types violations in @angular/upgrade.
@angular/upgradePlatform5
Supports TypeScript 5.8.
Supports TypeScript 5.7.
TypeScript versions less than 5.5 are no longer supported.
Drops support for TypeScript 5.4.
Adds support for TypeScript 5.6.
API changes
Generated by DepDelta from published .d.ts files. Not mixed with prose notes.
- changed:
constructor ɵAsyncAnimationRendererFactory(doc: Document, delegate: RendererFactory2, zone: NgZone, animationType: 'animations' | 'noop', moduleImpl?: Promise<{ ɵcreateEngine: (type: 'animations' | 'noop', doc: Document) => ɵAnimationEngine; ɵAnimationRendererFactory: typeof ɵAnimationRendererFactory }> | undefined) → constructor ɵAsyncAnimationRendererFactory(doc: Document, delegate: RendererFactory2, zone: NgZone, animationType: 'animations' | 'noop', moduleImpl?: Promise<{ ɵcreateEngine: (type: 'animations' | 'noop', doc: Document) => _AnimationEngine; ɵAnimationRendererFactory: typeof _AnimationRendererFactory }> | undefined) - changed:
static property ɵAsyncAnimationRendererFactory.ɵfac: i0.ɵɵFactoryDeclaration<ɵAsyncAnimationRendererFactory, never> → static property ɵAsyncAnimationRendererFactory.ɵfac: i0.ɵɵFactoryDeclaration<AsyncAnimationRendererFactory, never> - changed:
static property ɵAsyncAnimationRendererFactory.ɵprov: i0.ɵɵInjectableDeclaration<ɵAsyncAnimationRendererFactory> → static property ɵAsyncAnimationRendererFactory.ɵprov: i0.ɵɵInjectableDeclaration<AsyncAnimationRendererFactory> - added:
protected method ɵAsyncAnimationRendererFactory.componentReplaced(componentId: string): void
- removed:
export { ANIMATION_MODULE_TYPE } - changed:
class ɵInjectableAnimationEngine extends ɵAnimationEngine implements OnDestroy → class ɵInjectableAnimationEngine extends _AnimationEngine implements OnDestroy - changed:
constructor ɵInjectableAnimationEngine(doc: Document, driver: AnimationDriver, normalizer: ɵAnimationStyleNormalizer) → constructor ɵInjectableAnimationEngine(doc: Document, driver: AnimationDriver, normalizer: _AnimationStyleNormalizer) - changed:
static property BrowserAnimationsModule.ɵmod: i0.ɵɵNgModuleDeclaration<BrowserAnimationsModule, never, never, [typeof i1.BrowserModule]> → static property BrowserAnimationsModule.ɵmod: i0.ɵɵNgModuleDeclaration<BrowserAnimationsModule, never, never, [typeof BrowserModule]> - changed:
static property NoopAnimationsModule.ɵmod: i0.ɵɵNgModuleDeclaration<NoopAnimationsModule, never, never, [typeof i1.BrowserModule]> → static property NoopAnimationsModule.ɵmod: i0.ɵɵNgModuleDeclaration<NoopAnimationsModule, never, never, [typeof BrowserModule]> - changed:
static property ɵInjectableAnimationEngine.ɵfac: i0.ɵɵFactoryDeclaration<ɵInjectableAnimationEngine, never> → static property ɵInjectableAnimationEngine.ɵfac: i0.ɵɵFactoryDeclaration<InjectableAnimationEngine, never> - changed:
static property ɵInjectableAnimationEngine.ɵprov: i0.ɵɵInjectableDeclaration<ɵInjectableAnimationEngine> → static property ɵInjectableAnimationEngine.ɵprov: i0.ɵɵInjectableDeclaration<InjectableAnimationEngine> - added:
export { ANIMATION_MODULE_TYPE } from '@angular/core'
- added:
class BrowserModule - added:
const platformBrowser: (extraProviders?: StaticProvider[]) => PlatformRef - added:
constructor BrowserModule() - added:
function bootstrapApplication(rootComponent: Type<unknown>, options?: ApplicationConfig, context?: BootstrapContext): Promise<ApplicationRef> - added:
function createApplication(options?: ApplicationConfig): Promise<ApplicationRef> - added:
function provideProtractorTestingSupport(): Provider[] - added:
interface BootstrapContext - added:
property BootstrapContext.platformRef: PlatformRef - added:
static property BrowserModule.ɵfac: i0.ɵɵFactoryDeclaration<BrowserModule, never> - added:
static property BrowserModule.ɵinj: i0.ɵɵInjectorDeclaration<BrowserModule> - added:
static property BrowserModule.ɵmod: i0.ɵɵNgModuleDeclaration<BrowserModule, never, never, [typeof i1.CommonModule, typeof i0.ApplicationModule]> - added:
type ApplicationConfig = ApplicationConfig$1
- removed:
class BrowserModule - removed:
const platformBrowser: (extraProviders?: StaticProvider[]) => PlatformRef - removed:
const ɵINTERNAL_BROWSER_PLATFORM_PROVIDERS: StaticProvider[] - removed:
constructor BrowserModule(providersAlreadyPresent: boolean | null) - removed:
export { ɵgetDOM } - removed:
function bootstrapApplication(rootComponent: Type<unknown>, options?: ApplicationConfig, context?: BootstrapContext): Promise<ApplicationRef> - removed:
function createApplication(options?: ApplicationConfig): Promise<ApplicationRef> - removed:
function provideProtractorTestingSupport(): Provider[] - removed:
function ɵinitDomAdapter(): void - removed:
interface BootstrapContext - removed:
property BootstrapContext.platformRef: PlatformRef - removed:
readonly property ɵSharedStylesHost.platformId: object - removed:
static method BrowserModule.withServerTransition(params: { appId: string }): ModuleWithProviders<BrowserModule> - removed:
static property BrowserModule.ɵfac: i0.ɵɵFactoryDeclaration<BrowserModule, [{ optional: true; skipSelf: true }]> - removed:
static property BrowserModule.ɵinj: i0.ɵɵInjectorDeclaration<BrowserModule> - removed:
static property BrowserModule.ɵmod: i0.ɵɵNgModuleDeclaration<BrowserModule, never, never, [typeof i1.CommonModule, typeof i0.ApplicationModule]> - removed:
type ApplicationConfig = ApplicationConfig_2 - changed:
abstract method EventManagerPlugin.addEventListener(element: HTMLElement, eventName: string, handler: Function): Function → abstract method EventManagerPlugin.addEventListener(element: HTMLElement, eventName: string, handler: Function, options?: ListenerOptions): Function - changed:
class ɵBrowserDomAdapter extends GenericBrowserDomAdapter → class ɵBrowserDomAdapter extends _DomAdapter - changed:
constructor ɵDomRendererFactory2(eventManager: EventManager, sharedStylesHost: ɵSharedStylesHost, appId: string, removeStylesOnCompDestroy: boolean, doc: Document, platformId: Object, ngZone: NgZone, nonce?: string | null) → constructor ɵDomRendererFactory2(eventManager: EventManager, sharedStylesHost: SharedStylesHost, appId: string, removeStylesOnCompDestroy: boolean, doc: Document, platformId: Object, ngZone: NgZone, nonce?: string | null, tracingService?: _TracingService<_TracingSnapshot> | null) - changed:
constructor ɵHammerGesturesPlugin(doc: any, _config: HammerGestureConfig, console: ɵConsole, loader?: (HammerLoader | null) | undefined) → constructor ɵHammerGesturesPlugin(doc: any, _config: HammerGestureConfig, _injector: Injector, loader?: (HammerLoader | null) | undefined) - changed:
constructor ɵSharedStylesHost(doc: Document, appId: string, nonce?: (string | null) | undefined, platformId?: object) → constructor ɵSharedStylesHost(doc: Document, appId: string, nonce?: string | null | undefined, platformId?: object) - changed:
method EventManager.addEventListener(element: HTMLElement, eventName: string, handler: Function): Function → method EventManager.addEventListener(element: HTMLElement, eventName: string, handler: Function, options?: ListenerOptions): Function - changed:
method ɵBrowserDomAdapter.onAndCancel(el: Node, evt: any, listener: any): Function → method ɵBrowserDomAdapter.onAndCancel(el: Node, evt: any, listener: any, options: any): Function - changed:
method ɵDomEventsPlugin.addEventListener(element: HTMLElement, eventName: string, handler: Function): Function → method ɵDomEventsPlugin.addEventListener(element: HTMLElement, eventName: string, handler: Function, options?: ListenerOptions): Function - changed:
method ɵDomEventsPlugin.removeEventListener(target: any, eventName: string, callback: Function): void → method ɵDomEventsPlugin.removeEventListener(target: any, eventName: string, callback: Function, options?: ListenerOptions): void - changed:
method ɵKeyEventsPlugin.addEventListener(element: HTMLElement, eventName: string, handler: Function): Function → method ɵKeyEventsPlugin.addEventListener(element: HTMLElement, eventName: string, handler: Function, options?: ListenerOptions): Function - changed:
method ɵSharedStylesHost.addStyles(styles: string[]): void → method ɵSharedStylesHost.addStyles(styles: string[], urls?: string[]): void - changed:
method ɵSharedStylesHost.removeStyles(styles: string[]): void → method ɵSharedStylesHost.removeStyles(styles: string[], urls?: string[]): void - changed:
static property ɵDomEventsPlugin.ɵfac: i0.ɵɵFactoryDeclaration<ɵDomEventsPlugin, never> → static property ɵDomEventsPlugin.ɵfac: i0.ɵɵFactoryDeclaration<DomEventsPlugin, never> - changed:
static property ɵDomEventsPlugin.ɵprov: i0.ɵɵInjectableDeclaration<ɵDomEventsPlugin> → static property ɵDomEventsPlugin.ɵprov: i0.ɵɵInjectableDeclaration<DomEventsPlugin> - changed:
static property ɵDomRendererFactory2.ɵfac: i0.ɵɵFactoryDeclaration<ɵDomRendererFactory2, never> → static property ɵDomRendererFactory2.ɵfac: i0.ɵɵFactoryDeclaration<DomRendererFactory2, [null, null, null, null, null, null, null, null, { optional: true }]> - changed:
static property ɵDomRendererFactory2.ɵprov: i0.ɵɵInjectableDeclaration<ɵDomRendererFactory2> → static property ɵDomRendererFactory2.ɵprov: i0.ɵɵInjectableDeclaration<DomRendererFactory2> - changed:
static property ɵDomSanitizerImpl.ɵfac: i0.ɵɵFactoryDeclaration<ɵDomSanitizerImpl, never> → static property ɵDomSanitizerImpl.ɵfac: i0.ɵɵFactoryDeclaration<DomSanitizerImpl, never> - changed:
static property ɵDomSanitizerImpl.ɵprov: i0.ɵɵInjectableDeclaration<ɵDomSanitizerImpl> → static property ɵDomSanitizerImpl.ɵprov: i0.ɵɵInjectableDeclaration<DomSanitizerImpl> - changed:
static property ɵHammerGesturesPlugin.ɵfac: i0.ɵɵFactoryDeclaration<ɵHammerGesturesPlugin, [null, null, null, { optional: true }]> → static property ɵHammerGesturesPlugin.ɵfac: i0.ɵɵFactoryDeclaration<HammerGesturesPlugin, [null, null, null, { optional: true }]> - changed:
static property ɵHammerGesturesPlugin.ɵprov: i0.ɵɵInjectableDeclaration<ɵHammerGesturesPlugin> → static property ɵHammerGesturesPlugin.ɵprov: i0.ɵɵInjectableDeclaration<HammerGesturesPlugin> - changed:
static property ɵKeyEventsPlugin.ɵfac: i0.ɵɵFactoryDeclaration<ɵKeyEventsPlugin, never> → static property ɵKeyEventsPlugin.ɵfac: i0.ɵɵFactoryDeclaration<KeyEventsPlugin, never> - changed:
static property ɵKeyEventsPlugin.ɵprov: i0.ɵɵInjectableDeclaration<ɵKeyEventsPlugin> → static property ɵKeyEventsPlugin.ɵprov: i0.ɵɵInjectableDeclaration<KeyEventsPlugin> - changed:
static property ɵSharedStylesHost.ɵfac: i0.ɵɵFactoryDeclaration<ɵSharedStylesHost, [null, null, { optional: true }, null]> → static property ɵSharedStylesHost.ɵfac: i0.ɵɵFactoryDeclaration<SharedStylesHost, [null, null, { optional: true }, null]> - changed:
static property ɵSharedStylesHost.ɵprov: i0.ɵɵInjectableDeclaration<ɵSharedStylesHost> → static property ɵSharedStylesHost.ɵprov: i0.ɵɵInjectableDeclaration<SharedStylesHost> - added:
export { ApplicationConfig } from './browser.d-[hash]' - added:
export { BootstrapContext } from './browser.d-[hash]' - added:
export { BrowserModule } from './browser.d-[hash]' - added:
export { bootstrapApplication } from './browser.d-[hash]' - added:
export { createApplication } from './browser.d-[hash]' - added:
export { platformBrowser } from './browser.d-[hash]' - added:
export { provideProtractorTestingSupport } from './browser.d-[hash]' - added:
export { ɵgetDOM } from '@angular/common' - added:
function withIncrementalHydration(): HydrationFeature<HydrationFeatureKind.IncrementalHydration> - added:
member HydrationFeatureKind.IncrementalHydration = 4 - added:
protected method ɵDomRendererFactory2.componentReplaced(componentId: string): void - added:
protected method ɵSharedStylesHost.addUsage<T extends HTMLElement>(value: string, usages: Map<string, UsageRecord<T>>, creator: (value: string, doc: Document) => T): void - added:
protected method ɵSharedStylesHost.removeUsage<T extends HTMLElement>(value: string, usages: Map<string, UsageRecord<T>>): void - added:
readonly property ɵBrowserDomAdapter.supportsDOMEvents: boolean
- changed:
static property BrowserTestingModule.ɵmod: i0.ɵɵNgModuleDeclaration<BrowserTestingModule, never, never, [typeof i1.BrowserModule]> → static property BrowserTestingModule.ɵmod: i0.ɵɵNgModuleDeclaration<BrowserTestingModule, never, never, [typeof BrowserModule]>