Skip to content

SSR/Prerendering + Hydration for document fragments #67785

@eblocha

Description

@eblocha

Which @angular/* package(s) are relevant/related to the feature request?

core

Description

Overview

I'd like to be able to use Angular components in Astro islands with Angular's client hydration.

This is not currently possible today, because Angular expects to control the entire document during hydration.
It looks for an <!-- nghm --> comment node as the first child of the body, and throws an exception if this is not present.

Details

With Astro islands, the component is pre-rendered with a DOM structure similar to this:

<html>
    <head>
    </head>
    <body>
        <h1>Some page title</h1>
        ...
        <astro-island>
            <!-- the Angular integration can only control this content -->
            <ng-component>
                <!-- prerendered content -->
            </ng-component>
        </astro-island>
    </body>
</html>

To perform hydration, Astro expects a "framework integration" to provide a function that takes this <astro-island> element, the component definition, and original input properties.

Today, I am using the @analogjs/astro-angular package to perform this task. This performs hydration by throwing away the existing DOM and rerendering the component from scratch. https://github.com/analogjs/analog/blob/beta/packages/astro-angular/src/client.ts#L26

Side note: it also currently does pre-rendering with Angular's renderApplication, which produces an entire document on its own. See withastro/roadmap#1322

Initial Attempt

I have tried enabling client hydration with the Analog integration, by adding the provideClientHydration providers here and here.

This produces a DOM structure like this:

<html>
    <head>
    </head>
    <body>
        <h1>Some page title</h1>
        ...
        <astro-island>
            <!-- nghm -->
            <ng-component>
                <!-- prerendered content -->
            </ng-component>
            <script id="ng-state" type="application/json">{"__nghData__":[...]}</script>
        </astro-island>
    </body>
</html>

When Angular is doing client hydration, it looks for <!-- nghm --> as the first child in the body, but throws because it's not there, assuming the DOM it originally rendered had been modified.

Proposed solution

The ask of this feature is to support hydration for fragments of the document, where Angular is given a containing element (the island), and treats that as the document body.

This would allow Analog to leverage Angular's client-side hydration, and reuse the DOM that is in place from prerendering.

I am imagining an API similar to this:

export const appConfig: ApplicationConfig = {
  providers: [
    provideBrowserGlobalErrorListeners(),
    provideClientHydration(withEventReplay()),
    /* NEW: */ provideClientHydrationHost(htmlElement),
  ]
};

The htmlElement would be the <astro-island> component I described above.

This would "scope" the hydration to just its host element container. This provider would only be present on the client.

I'm also thinking that @angular/platform-server could provide a function similar to renderApplication, but produces 2 parts instead of the whole document: the body content, and the head content. This would allow an app rendering islands to more easily control how that content gets inserted into the DOM.

const { body, head } = renderApplicationParts(bootstrap);

Alternatives considered

An alternative is to throw away the existing DOM as Analog does today.

Analog could also mess with the <!-- nghm --> node and put it somewhere that Angular is "happy" with, but that couples it to internal implementation details, and falls apart when there is more than one island on the page.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: coreIssues related to the framework runtimegemini-triagedLabel noting that an issue has been triaged by gemini

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions