bug: Stencil dev server CSS updates are broken when using dist-hydrate-script
#3461
Closed
3 tasks done
Labels
Bug: Validated
This PR or Issue is verified to be a bug within Stencil
Prerequisites
Stencil Version
2.17.0
Current Behavior
summary: if
dist-hydrate-script
output target is set then CSS hot-reload is broken and changing a CSS file will result in components losing all of their styling.This problem has to do with how we rewrite CSS in order to support scoped components, an alternative way to scope styles to a component which does not use the shadow DOM. We have a utility function, defined in
src/utils/shadow-css.ts
, which rewrites a CSS string in order to 'scope' it within a component by rewriting the selectors to include a unique ID. This function is called in the dev server workflow in such a way that CSS gets mangled if (possibly iff):shadow: true
anddist-hydrate-script
output target is set in the Stencil configurationThis results in styles targeting the
:host
selector to be rewritten to a different selector, wiping styles from the component when the updated CSS is applied to the page in the browser.Why is this happening?
The
scopeCss
function is defined here:stencil/src/utils/shadow-css.ts
Line 418 in 658fdd8
This function is called when the dev server is processing a change event to a CSS file. The function is called in the
transformCssToEsmModule
function insrc/compiler/style/css-to-esm.ts
:stencil/src/compiler/style/css-to-esm.ts
Lines 115 to 120 in 658fdd8
The third argument to the function is here set to
input.commentOriginalSelector
, which causes the CSS selectors to be commented out (see below). This causes CSS using the:host
selector for styling the component's shadow DOM to be mangled in such a way that the styles don't apply to anything.The third argument is set in the
extTransformsPlugin
, here:stencil/src/compiler/bundle/ext-transforms-plugin.ts
Lines 54 to 65 in 658fdd8
and here:
stencil/src/compiler/bundle/ext-transforms-plugin.ts
Line 34 in 658fdd8
bundleOpts.platform
is in turn set to"hydrate"
in theBundleOptions
object constructed inbundleHydrateFactory
, here:stencil/src/compiler/output-targets/dist-hydrate-script/bundle-hydrate-factory.ts
Lines 19 to 31 in 658fdd8
which is in turn called in the
generateHydrateApp
function which does the main work for thedist-hydrate-script
output target:stencil/src/compiler/output-targets/dist-hydrate-script/generate-hydrate-app.ts
Line 83 in 658fdd8
stencil/src/compiler/output-targets/dist-hydrate-script/index.ts
Lines 5 to 14 in 658fdd8
Anyhow, to make a long story short, when the
dist-hydrate-script
output target is set then CSS will be 'scoped' using thescopeCss
function with thecommentOriginalSelector
argument set totrue
, even in situations in which it isn't appropriate to do so, and in particular, when a component does not havescoped: true
and instead hasshadow: true
. This will cause CSS like:to be rewritten like
This, in turn, results in the CSS not applying to the component, and we get a nice, unstyled component instead of what we want.
Why doesn't this happen on the first page load?
I believe this doesn't happen on first page load because on first page load CSS is processed in the
initializeComponent
function but in that instance it is not called with thecommentOriginalSelector
argument set totrue
:stencil/src/runtime/initialize-component.ts
Lines 104 to 111 in 658fdd8
Expected Behavior
The hot module reload functionality in the dev server should work, i.e. edits made in the CSS file for a component should be reflected in the browser automatically without having to reload the page.
Steps to Reproduce
There are detailed instructions in the reproduction repo.
Code Reproduction URL
https://github.com/alicewriteswrongs/stencil-hmr-hydrate-repro
Additional Information
No response
The text was updated successfully, but these errors were encountered: