Skip to content

bug: renderToString in AstroJS breaks hydration without error messages #6746

@rriemann

Description

@rriemann

Prerequisites

Framework Output Target

SSR (@stencil/ssr)

Output Target Version

don't know. I use 0.26.0 from https://github.com/ec-europa/ecl-webcomponents/tree/ecl-v5-dev

Stencil Version

4.43.4

Reproduction URL

https://gitlab.com/rriemann/astro-ecl-stenciljss-bug/

Describe the Bug

I use the following middleware in Astrojs to apply SSR (code curtesy of @johnjenkins on discord):

import { defineMiddleware } from "astro:middleware";
import { renderToString } from "@ecl/ecl-webcomponents-hydrate";

// snippet from https://discord.com/channels/1347590794130755665/1501974928814247996

export const onRequest = defineMiddleware(async (ctx, next) => {
  const response = await next();

  const contentType = response.headers.get("content-type") || "";

  const { url } = ctx.request;
  const { pathname } = new URL(url);
  console.log(`[Middleware] Incoming request to: ${pathname}`);

  if (contentType.includes("text/html") && pathname.includes("ssr")) {
    const html = await response.text();

    const results = await renderToString(
      html,
      {
        fullDocument: true,
        serializeShadowRoot: 'declarative-shadow-dom',
        prettyHtml: true,
      }
    )

    return new Response(results.html, {
      status: response.status,
      headers: response.headers,
    });
  }

  return response;
});

This code runs only on pages with ssr in path.

The demo at https://gitlab.com/rriemann/astro-ecl-stenciljss-bug/ shows that for small-factor windows (mobile view), the website header is broken when using renderToString.

Steps to Reproduce

See in action on Gitlab pages

Check out Gitlab Pages at https://astro-ecl-stenciljss-bug-19f0dd.gitlab.io/ and test both pages in mobile view:

Reproduce locally

To see the software problem follow these steps:

  1. git clone https://gitlab.com/rriemann/astro-ecl-stenciljss-bug the repo

  2. pnpm install the dependencies

  3. pnpm dev to run the development server

  4. visit the index page / without SSR and switch your browser in mobile view (e.g. using browser developer tools). The menu button and the search button are in the same line (same distance to page top).
    Image

  5. visit the page /ssr with SSR in the same mobile view and notice that the search button is in a different line.
    Image

Expected Behavior

SSR should not lead to different HTML.

Additional Context

SSR (not working, from webdeveeloper toolbar):

<div class="ecl-container ecl-site-header__container sc-ecl-site-header-ec">
    <a c-id="922.0.0.0" class="ecl-link ecl-link--standalone ecl-site-header__logo-link sc-ecl-link-ec sc-ecl-link-ec-s sc-ecl-site-header-ec">
        <!--s.922.1.1.0.-->
        <ecl-link class="sc-ecl-site-header-ec sc-ecl-link-ec-h hydrated">
            <!---->
            <a class="ecl-link ecl-site-header__logo-link sc-ecl-site-header-ec ecl-link--standalone sc-ecl-link-ec sc-ecl-link-ec-s">
                <ecl-picture class="sc-ecl-site-header-ec sc-ecl-picture-ec-h hydrated">
                    <!---->
                    <picture class="ecl-picture ecl-site-header__picture sc-ecl-picture-ec sc-ecl-picture-ec-s sc-ecl-site-header-ec-s">
                        <source srcset="/build/images/ec/logos/positive/logo-ec--en.svg" media="(min-width: 415px)" class="sc-ecl-site-header-ec"><img src="/build/images/ec/logos/logo-ec--mute.svg" class="ecl-site-header__logo-image ecl-site-header__logo-image--l sc-ecl-site-header-ec sc-ecl-picture-ec" alt="European Commission"></picture>
                </ecl-picture>
            </a>
        </ecl-link>
    </a>
    <div class="ecl-site-header__top sc-ecl-site-header-ec" data-ecl-site-header-top="">

        <ecl-link class="hydrated sc-ecl-link-ec-h sc-ecl-site-header-ec" s-mode="ec">
            <!--r.922-->
            <a class="ecl-link sc-ecl-link-ec sc-ecl-link-ec-s">

            </a>
        </ecl-link>

And this this the SSR version (downloaded from the server, view source code in firefox, not working):

<div c-id="3090.3.3.0" class="ecl-container ecl-site-header__container sc-ecl-site-header-ec">
  <div c-id="3090.4.4.0" class="ecl-site-header__top sc-ecl-site-header-ec" data-ecl-site-header-top>
    <a c-id="3092.0.0.0" class="ecl-link ecl-link--standalone ecl-site-header__logo-link sc-ecl-link-ec sc-ecl-link-ec-s sc-ecl-site-header-ec">
      <!--s.3092.1.1.0.-->
      <ecl-picture c-id="3090.6.6.0" class="hydrated sc-ecl-picture-ec-h sc-ecl-site-header-ec" s-id="3091" s-mode="ec" s-sn="">
        <!--r.3091-->
        <!--o.3090.7.c-->
        <!--o.3090.8.c-->
        <picture c-id="3091.0.0.0" class="ecl-picture ecl-site-header__picture sc-ecl-picture-ec sc-ecl-picture-ec-s sc-ecl-site-header-ec-s">
          <!--s.3091.1.1.0.-->
          <source c-id="3090.7.7.0" class="sc-ecl-site-header-ec" media="(min-width: 415px)" s-sn="" srcset="/build/images/ec/logos/positive/logo-ec--en.svg">
          <!--s.3090.8.7.1.logoSources-->
          <img alt="European Commission" c-id="3091.2.1.1" class="ecl-site-header__logo-image ecl-site-header__logo-image--l sc-ecl-picture-ec sc-ecl-site-header-ec" src="/build/images/ec/logos/logo-ec--mute.svg">
        </picture>
      </ecl-picture>
    </a>
    <ecl-link c-id="3090.5.5.0" class="hydrated sc-ecl-link-ec-h sc-ecl-site-header-ec" s-id="3092" s-mode="ec">
      <!--r.3092-->
      <!--o.3090.6.c-->
    </ecl-link>
    <div c-id="3090.9.5.1" class="ecl-site-header__action sc-ecl-site-header-ec">
      <div c-id="3090.10.6.0" class="ecl-site-header__login-container sc-ecl-site-header-ec"></div>
      <!--t.3090.11.6.1-->
      <div c-id="3090.12.6.2" class="ecl-site-header__search-container sc-ecl-site-header-ec" role="search">

You can see that the order and nesting of the tags have changed of the SSR page between before and after hydration.

Logs


Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions