Introduces support for route-level resources via the `resources` property on route definitions, enabled with `withRouterResources()`.
Router resources provide a reactive, signal-based alternative to resolvers, allowing routes to declare resources tied to route parameters and route lifecycle:
- The `resources` function executes during navigation transitions within an injection context scoped to the route (`_localInjector`).
- It receives a `ResourceContext` containing signals for `params`, `queryParams`, `fragment`, and `data`, alongside the static `snapshot`.
- For newly created routes, `resources` runs once and attaches to `ActivatedRoute.resources`. For reused routes, parameter signals update reactively to trigger new data fetches while keeping resource references stable.
- Wrapped resources (`routerResource`) provide transactional stability: snapshots are frozen during active navigations to prevent UI jitter, unfreezing on `NavigationEnd`.
- On cancelled navigations or errors, rollback recovery retains the frozen snapshot until reverted signals settle, avoiding flashes of loading state. Manual reloads are rejected while frozen.
- Local injectors are automatically cleaned up if navigations are cancelled or rolled back.
Note that this commit only implements non-blocking resources (marked with `nonBlocking()`), deferring blocking resource resolution to future work to keep the initial changeset smaller and less complex.
PR Close#70211
This commit updates `@defer` logic related to incremental hydration to be tree-shakable.
If hydrate triggers are used in a `@defer` block, the compiler emits a single top-level call to `ɵɵenableIncrementalHydrationRuntime`, placed once per create block before the first `ɵɵdefer` that requires it.
As a result, the incremental hydration runtime is only included in the bundle when hydrate is explicitly used.
This is a minimal implmentation which just focuses on registering parent shadow roots in `SharedStylesHost` correctly.
We don't currently reference count usage of host values, meaning that as soon as we call `removeHost`, all styles are removed from it, even if other components relied on them. Therefore there is no good way to know whether styles are still needed or not, leaving us with the choice of either leaking them longer than necessary or destroying them while another component still needs them. The compromise I'm using here is to delete styles when destroying a component under a shadow root (based on the assumption that only one component will exist per shadow root) and to leave styles when destroying a component in the main document (based on the assumption that dialogs being destroyed should not impact the main application).
Neither assumption is totally safe to make, but we're hoping this is a viable balance for the moment. In the future we should look into lifting these restrictions to better support those use cases while properly reference counting usage of hosts in `SharedStylesHost`.
I also added some small tests to confirm that SSR styles are not duplicated, as an earlier implementation accidentally duplicated them. This should ensure we don't repeat that mistake.
This commit updates provideClientHydration to automatically enable incremental hydration by default. It also introduces a new withNoIncrementalHydration feature for opting out, adds conflict safety checks, and includes a schematic migration.
This is to align the shape of the method with `createComponent`
BREAKING CHANGE:The second arguement of appRef.bootstrap does not accept `any` anymore. Make sure the element you pass is not nullable.
fixes#67946
This new signal property is convenient to derive a `isNavigating` state.
`isNavigating = computed(() => !!this.router.currentNavigation())`
DEPRECATED: The Router.getCurrentNavigation method is deprecated. Use the Router.currentNavigation signal instead.
fixes#62958
PR Close#63011
This new signal property is convenient to derive a `isNavigating` state.
`isNavigating = computed(() => !!this.router.currentNavigation())`
DEPRECATED: The Router.getCurrentNavigation method is deprecated. Use the Router.currentNavigation signal instead.
fixes#62958
PR Close#62971