stencil icon indicating copy to clipboard operation
stencil copied to clipboard

`dist-hydrate-script` output target doesn't respect `hydratedFlag` config

Open nick-vincent opened this issue 2 years ago • 10 comments

Stencil version:

@stencil/[email protected]

Current behavior:

When using the dist-hydrate-script output target for SSR:

renderToString() always adds the class hydrated instead of respecting the hydratedFlag attribute configuration:

image

Expected behavior:

I would expect hydration via renderToString() to correctly respect the hydratedFlag attribute configuration:

image

GitHub Reproduction Link:

Here is my basic stencil repo: https://github.com/nick-vincent/gradient

I have the hydratedFlag set to attribute here and my output target as dist-hydrate-script here.

When you run npm run start inside web-components, Storybook correctly respects the hydratedFlag config.

However, if you inspect the built files, in /web-components/dist/hydrate/index.js the hydrated class is always added:

addHydratedFlag = e => e.classList.add('hydrated'),

Other Information

Edit: Upon further inspection, it appears that you can configure the name of the hydratedFlag:

hydratedFlag: {
  selector: 'attribute',
  name: 'yo-dawg'
}

And the built file /web-components/dist/hydrate/index.js does change the flag name, but it still uses a class instead of an attribute:

addHydratedFlag = e => e.classList.add('yo-dawg')

nick-vincent avatar Sep 14 '22 04:09 nick-vincent

@nick-vincent thanks for filing the issue, and for providing a reproduction! It's a big help for us when going through and triaging issues.

I've taken a look at your repro and read through some of the relevant code and I believe that you're right that renderToString does not currently respect the hydratedFlag setting.

Can you explain what you mean by the following?

Upon further inspection, it appears that you can change the classname, but it won't let you use selector: attribute:

I'm just wondering where you changed it such that it affected the built output, and what specifically wasn't working with selector: attribute.

Thanks!

alicewriteswrongs avatar Sep 19 '22 16:09 alicewriteswrongs

Hi @alicewriteswrongs, thanks for your reply!

Apologies I wasn't clearer about the last bit. What I mean is that you can configure the name of the hydratedFlag:

hydratedFlag: {
  selector: 'attribute',
  name: 'yo-dawg'
}

And the built file /dist/hydrate/index.js does change the flag name, but it still uses a class instead of an attribute:

addHydratedFlag = e => e.classList.add('yo-dawg')

I'd be happy to submit a PR for this, but I had trouble tracking down where this logic lives in the compiler.

nick-vincent avatar Sep 19 '22 17:09 nick-vincent

Thanks for the issue! This issue is being closed due to inactivity. If this is still an issue with the latest version of Stencil, please create a new issue and ensure the template is fully filled out.

Thank you for using Stencil!

ionitron-bot[bot] avatar Oct 19 '22 17:10 ionitron-bot[bot]

Sorry about that! Reopening

rwaskiewicz avatar Oct 20 '22 18:10 rwaskiewicz

@nick-vincent sorry to miss your earlier message! I'm going to label this so it can be prioritized. Thanks for reporting!

alicewriteswrongs avatar Oct 25 '22 20:10 alicewriteswrongs

Despite dist-hydrate-script itself, it's actually a useful feature to set hydrated with attribute instead of class, because it's very common to use custom classes on our tags when implementing them.

I'm giving an example of why this is critical :) For instance, with Vue3 if you apply conditional classes (binded from a reactive property) on your webcomponents, it breaks the style because hydrated class is overriden by Vue. If you have the invisiblePrehydration flag set to true, well then you don't see your elements (In a dist output/cdn/lazy-loaded components context)

<template>
   <my-custom-element :class="{ customClass: isCustomClass }"></my-custom-element>
<template>

<script setup>
import {ref} from 'vue';

const isCustomClass = ref(true); // playing with this overrides hydrated class

</script>

Applying attribute is then a pretty handy solution, I use it for a year now. But with the issue mentioned by @nick-vincent , that I'm facing as well, dist-hydrate-script is not easy to use IMHO.

KevinCarnaille2 avatar Jan 28 '23 11:01 KevinCarnaille2

@alicewriteswrongs I'm experiencing the same behavior with dist-custom-elements. Would you prefer a separate issue to be reported, or can it be tacked on to this one?

krivaten avatar Apr 19 '23 21:04 krivaten

Maybe let's go with another issue so we can track it separately in case there's a different root cause for the same behavior? I don't know that's the case, but it will help us to have a dist-custom-elements specific reproduction as well.

If they have the same root cause we'll just close both of them when we fix anyhow!

alicewriteswrongs avatar Apr 20 '23 14:04 alicewriteswrongs

Is there any update on this issue? I'm getting similar problem with hydrated class and sveltekit double hydration (once from stenciljs, then svelte hydration removing the hydrate class). For now we are using

hydratedFlag: {
    name: '',
  },

It's working as expected, but a bit worried about all potential impact of that trick. We also tried hydratedFlag: null but it's ignored similar to selector: 'attribute'.

FrancoisDF avatar Mar 03 '24 13:03 FrancoisDF

Sorry for the slow progress on this issue!

I've just taken another look at it, and I've got a bit of a fix together -- I'm not sure it's the best way of addressing the issue, but I'd love to know if it does fix the problem for anyone who's experiencing this.

You can install it like so:

npm install @stencil/[email protected]

alicewriteswrongs avatar May 08 '24 20:05 alicewriteswrongs

A fix for this was included in today's v4.18.2 release!

tanner-reits avatar May 20 '24 18:05 tanner-reits