This commit updates the `@angular/common/http` and `@angular/platform-server` packages to allow dynamic import of the `xhr2` dependency. The `xhr2` dependency has side-effects that rely on a global scope and as a result in some environments those side-effectful calls fail. With the changes from this PR, the import is delayed until it's actually needed, which gives a chance for the underlying platform to setup global scope (via shims) as needed.
Co-authored-by: alan-agius4 <17563226+alan-agius4@users.noreply.github.com>
PR Close#50095
Using `@angular/platform-browser-dynamic` is no longer required for JIT scenarios with Ivy. Instead `@angular/compiler` should be imported instead.
This change is part of the effort to reduce the server bundles sizes, which is needed to support cloud workers.
BREAKING CHANGE:
Users that are using SSR with JIT mode will now need to add `import to @angular/compiler` before bootstrapping the application.
**NOTE:** this does not effect users using the Angular CLI.
PR Close#50064
This commit refactors the logic of the `platform-server` to avoid using `platformDynamicServer` when `ngJitMode` is disabled. This is needed to avoid including JIT compiler into the source code of the server bundle, when this compil
er is not needed.
PR Close#50007
This adds context to the error message in the case that a DOM node is not found during the hydration process. It outputs the expected DOM structure based on the lView and tNode rather than an unhelpful text message.
PR Close#49977
Hydration relies on a signal from ZoneJS when it becomes stable inside an application, so that Angular can start serialization process on the server or post-hydration cleanup on the client (to remove DOM nodes that remained unclaimed).
Providing a custom or a "noop" ZoneJS implementation may lead to a different timing of the "stable" event, thus triggering the serialization or the cleanup too early or too late. This is not yet a fully supported configuration.
This commit adds a warning (non-blocking) for those cases.
PR Close#49944
This commit updates hydration logic to hanlde a case when the same component is used multiple times in a template and in some of those cases, component is opted-out of hydration, for example:
```
<cmp ngSkipHydration />
<cmp />
```
Previously, the first occurrence of the `<cmp>` would result in storing the `ssrId` on a TView as `null` (since hydration is disabled for the component) and the second component instance reused the `null` as a value, thus also skipping hydration.
With the changes from this commit, the `ssrId` would be set when we come across a hydratable instance. We also make sure that the `ssrId` value never changes after we first set it to a non-`null` value.
PR Close#49943
This commit updates hydration logic to handle cases when there are projection slots present in a template inside of an `<ng-container>` and when there are regular elements follow an <ng-content> slot (see tests for additional information). With this combination, the logic that annotates regular element locations should fallback to calculating a path from a reference node to that node. In case of an <ng-container>, the comment node is located *after* the node that needs an annotation. An existing logic was mistakenly returning an empty path, which was represented as a pointer to teh reference node. This commit fixes that and triggers a fallback to using a component host node as a reference in this case.
Resolves#49918.
PR Close#49920
Empty text nodes are not present in the server-rendered HTML output, thus we inject a special marker
at a text node location to later restore an empty text node at the client. Currently, we treat text nodes with spaces as "empty" as well, however those spaces are present in the HTML and text nodes are created in a browser. Adding extra annotation in this case results in extra text nodes created on the client and may trigger hydration issues. This commit updates the code to avoid treating text nodes with spaces as "empty".
PR Close#49877
Currently, the `ViewRef.rootNodes` output is missing anchor (comment) nodes for inner `ViewContainerRef`s,
when an achor node was created for that instance of a `ViewContainerRef` (which happens in all cases except
when an <ng-container> was used as a host for a view container).
This issue affects hydration logic, which relies on the number of root nodes within a view to properly determine
segments in DOM that belong to a particular view.
Resolves#49849.
PR Close#49867
The change in 8c3b92cfb3 inspired a followup refactor where the `_render` method can just accept a PlatformRef and an ApplicationRef instances directly.
PR Close#49851
This commit renames an internal token to better align it with the naming of the function (to highlight the fact that it's responsible for DOM part of the hydration).
PR Close#49800
This commit updates the logic that adds the "ng-server-context" attribute to the root elements to also include information about SSR feature enabled got an application.
PR Close#49773
This commit updates the minimum supported Node version across packages from 16.13.0 -> 16.14.0 to ensure compatibility with dependencies.
PR Close#49771
This commit updates the logic to avoid enabling hydration in case server response doesn't contain hydration-related info serialized. It can happen when `provideClientHydration()` call only happens on the client, but not on the server.
PR Close#49750
This commit updates the logic to detect a situation when hydration support was enabled only on the client. If that happens, Angular produces a warning in a console with a link to the error guide.
PR Close#49743
The Domino DOM emulation library doesn't support shadow DOM. For such components we can not guarantee that client and server representations would match perfectly. To avoid hydration mismatch errors, such components are opted out of hydration.
PR Close#49722
Currently, non-destructive hydration for i18n blocks is not supported (but support is coming!).
This commit updates the serialization logic from throwing an error when it comes across an i18n
block to annotating a component with a skip hydration flag.
PR Close#49722
This commit adds support by default for HTTP caching when using `provideClientHydration`. Users can opt-out of this behaviour by using the `withoutHttpTransferCache` feature.
```ts
import {
bootstrapApplication,
provideClientHydration,
withNoHttpTransferCache,
} from '@angular/platform-browser';
// ...
bootstrapApplication(RootCmp, {
providers: [provideClientHydration(withNoHttpTransferCache())]
});
```
PR Close#49699
This commit adds the `provideClientHydration` function to the public API. This function can be used to enable the non-destructive Angular hydration.
Important note: the non-destructive hydration feature is in Developer Preview mode, learn more about it at https://angular.io/guide/releases#developer-preview.
Before you can get started with hydration, you must have a server side rendered (SSR) application. Follow the [Angular Universal Guide](https://angular.io/guide/universal) to enable server side rendering first. Once you have SSR working with your application, you can enable hydration by visiting your main app component or module and importing `provideClientHydration` from `@angular/platform-browser`. You'll then add that provider to your app's bootstrapping providers list.
```typescript
import {
bootstrapApplication,
provideClientHydration,
} from '@angular/platform-browser';
// ...
bootstrapApplication(RootCmp, {
providers: [provideClientHydration()]
});
```
Alternatively if you are using NgModules, you would add `provideClientHydration` to your root app module's provider list.
```typescript
import {provideClientHydration} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
@NgModule({
declarations: [RootCmp],
exports: [RootCmp],
bootstrap: [RootCmp],
providers: [provideClientHydration()],
})
export class AppModule {}
```
You can confirm hydration is enabled by opening Developer Tools in your browser and viewing the console. You should see a message that includes hydration-related stats, such as the number of components and nodes hydrated.
Co-authored-by: jessicajaniuk <72768744+jessicajaniuk@users.noreply.github.com>
Co-authored-by: alan-agius4 <17563226+alan-agius4@users.noreply.github.com>
PR Close#49666
This commit updates the logic to handle a case when the `ngSkipHydration` attribute is applied to the root node of an app. In this case, the hydration info should not be serialized and the contents of the app on the client should be cleared up before initial rendering.
PR Close#49675
This commit removed the deprecated `EventManager` method `addGlobalEventListener`.
BREAKING CHANGE: Deprecated `EventManager` method `addGlobalEventListener` has been removed as it is not used by Ivy.
PR Close#49645
This commit adds a logic to output basic hydration stats into a console. This is also helpful to ensure that hydration is enabled and works.
PR Close#49617
This commits adds `makeStateKey`, `StateKey` and `TransferState` methods in `@angular/core` as public API and deprecated the same exported symbols in `@angular/platform-browser`.
DEPRECATED: `makeStateKey`, `StateKey` and `TransferState` exports have been moved from `@angular/platform-browser` to `@angular/core`. Please update the imports.
```diff
- import {makeStateKey, StateKey, TransferState} from '@angular/platform-browser';
+ import {makeStateKey, StateKey, TransferState} from '@angular/core';
```
PR Close#49563
These two options where created for a feature which was never completed. https://github.com/angular/universal/pull/1860
Eventually these options should be added to `withTransferCache` HTTP logic.
DEPRECATED: `PlatformConfig.baseUrl` and `PlatformConfig.useAbsoluteUrl` platform-server config options are deprecated as these were not used.
PR Close#49546
This commit adds a background macrotask when an XHR request is performed. The macrotask is started during `loadstart` and ended during `loadend` event.
The macrotask is needed so that the application is not stabilized during HTTP calls. This is important for server rendering, as the application is rendering when the application is stabilized.
The application is stabilized when there are no longer pending Macro and Micro tasks intercepted by Zone.js, Since an XHR request is none of these, we create a background macrotask so that Zone.js is
made aware that there is something pending.
Prior to this change, we patched the `HttpHandler` in `@angular/platform-server` but this is not enough, as there can be multiple `HttpHandler` in an application, example when importing `HttpClient` in a lazy loaded component/module.
Which causes a new unpatched instance of `HttpHandler` to be created in the child injector which is not intercepted by Zone.js and thus the application is stabalized and rendered before the XHR request is finalized.
NB: Zone.js is fundamental for SSR and currently, it's not possible to do SSR without it.
Closes: #49425
PR Close#49546
This commit implements a simple tracker of the pending tasks during initial rendering. The class allows adding and removing tasks from the set. The class also exposes a promise that gets resolved once the last task is removed.
This tracker is needed to keep track of ongoing processes like Router navigation (and potentially HTTP requests) and acts as a signaling mechanism to SSR and hydration that the application is in the "stable" state and a serialization can be performed.
This class would also act as a future replacement for the `ApplicationRef.isStable` for zoneless applications.
PR Close#49576
This commit updates the serialization logic to avoid serializing a path for a node that was content projected (based on template information), but is not present in the DOM. This can happen if a <ng-content> is used with the *ngIf="false", for example: `<ng-content *ngIf="false" />`.
PR Close#49590
Previously, we've annotated all disconnected DOM nodes, even if they are not used in content projection. However, this situation is only possible in content projection and if it happens in other cases (for example, when a node was removed using direct DOM manipulations), this should be a mismatch error.
PR Close#49549
Several updates to Angular Package Format.
BREAKING CHANGE:
Several changes to the Angular Package Format (APF)
- Removal of FESM2015
- Replacing ES2020 with ES2022
- Replacing FESM2020 with FESM2022
PR Close#49559
Several updates to Angular Package Format.
BREAKING CHANGE:
Several changes to the Angular Package Format (APF)
- Removal of FESM2015
- Replacing ES2020 with ES2022
- Replacing FESM2020 with FESM2022
PR Close#49332
This adds user friendly error messages outlining exactly where hydration
mismatches occur and what was expected with easy to read stringified
DOM. It also includes a pointer to exactly where the mismatch happened
and lets the user know what was expected.
PR Close#49502
This commit updates the hydration logic to handle situations where DOM nodes might end up
being disconnected from the DOM tree. We serialize ids of those nodes into the hydration
state transfer data and use the information to switch from hydration to the regular "creation
mode" at runtime.
This situation may happen during the content projection, when some nodes don't make it
into one of the content projection slots (for example, when there is no default
<ng-content /> slot in projector component's template).
Note: we leverage the fact that we have this information available in the DOM emulation
layer (in Domino) for now. Longer-term solution should not rely on the DOM emulation and
only use internal data structures and state to compute this information.
PR Close#49471
This commit removes the `renderApplication` overload that accepts a root component as the first parameter.
BREAKING CHANGE:
`renderApplication` method no longer accepts a root component as first argument. Instead, provide a bootstrapping function that returns a `Promise<ApplicationRef>`.
Before
```ts
const output: string = await renderApplication(RootComponent, options);
```
Now
```ts
const bootstrap = () => bootstrapApplication(RootComponent, appConfig);
const output: string = await renderApplication(bootstrap, options);
```
PR Close#49463
This commit updates the serialization logic to detect a situation when i18n was used for a template and throw an error to indicate that hydration for i18n blocks is not yet supported.
Hydration for i18n blocks will be added in follow up versions.
PR Close#49497
Angular Hydration uses Components as a hydration boundary, i.e. you can enable/disable hydration on per-component basis. This commit enforces that the `ngSkipHydration` can only be applied on component host nodes (an error if thrown otherwise).
PR Close#49500
This commit updates the serialization logic to recognized similar repeated views and instead of including the same info over and over again, a special field is added to the serialized view object with a number of repetitions. The hydration logic also recognizes the flag and creates the necessary number of dehydrated views in a container.
This optimization should help minimize the amount of extra annotations required for cases like *ngFor with large number of items.
PR Close#49475
This commit adds a logic to remove all views that were not cleaimed during the hydration. The process is started once the ApplicationRef becomes stable on the client (which matches the timing of serialization on the server).
PR Close#49455
This commit adds serialization and hydration logic for content projection.
While hydration for regular elements relies on their location in the TNode tree, the content projection may move elements around, so in order to hydrate them correcty, the runtime needs some extra information. This commit adds a serialization logic that adds element locations (instructions on how to navigate to a particular element from another known location of other element) into the hydration state for the following cases:
- when a TNode is a first element in projection segment (other nodes are linked from that node)
- when a TNode's next sibling is different before and after projection (we serialize extra info about the template-based sibling)
- when a TNode's previous sibling was a content projection (i.e. `<ng-content>` slot), because we can not rely on the previous element in this case (projection happens at a later point)
PR Close#49454
This commit adds serialization and hydration logic for content projection.
While hydration for regular elements relies on their location in the TNode tree, the content projection may move elements around, so in order to hydrate them correcty, the runtime needs some extra information. This commit adds a serialization logic that adds element locations (instructions on how to navigate to a particular element from another known location of other element) into the hydration state for the following cases:
- when a TNode is a first element in projection segment (other nodes are linked from that node)
- when a TNode's next sibling is different before and after projection (we serialize extra info about the template-based sibling)
- when a TNode's previous sibling was a content projection (i.e. `<ng-content>` slot), because we can not rely on the previous element in this case (projection happens at a later point)
PR Close#49454
`ng-app` is an AngularJS attribute, see https://docs.angularjs.org/api/ng/directive/ngApp. Using this attribute on a non AngularJS element can cause DI issues in AngularJS when running an AngularJS and Angular application on the same page.
As such, we avoid such problems the Angular `ng-app` attribute is renamed to `ng-app-id`.
PR Close#49424
This restores the separation between adjacent text nodes that is lost during server serialization when parsed by the browser. It adds a special comment node just prior to the serialization process that is then restored as a separated node during hydration.
PR Close#49419