Open mayerraphael opened 1 year ago
oooooo, hydrate - I thought I had fixed that đ đ¤Ļââī¸ Come to think of it, our bigger project did show some interesting artefacts when we turned hydrate on, but in the end we reverted back to static generation so didn't need hydrate so never investigated them further.
Do you know if this happens on the example repo, or have a example to play with?
Also, the code drop here ... is this your plugin or an example of a/the fix?
I removed the code from the original post, you can find our adjusted plugin here: https://gist.github.com/mayerraphael/bb3122ece5900671b5cb85dbe46a1e8e
I will check your example repo later.
It looks like the tailwindHMR plugin is required to correctly generate the Hydrate classes. We only had the tailwindCss
plugin set.
Interesting ... the HMR plugin add dependencies and writes the css to stencil buffers. I'm guessing the secondary buffer write is probably what does it seeing that the HMR only deals with the CSS files and updates stencils css files.
Should probably make that more explicit if that is the cause - like an actual plugin/implementation that maps better to hydrate.
Yes the problem is that only the css transform plugins run before Stencils Hydrate worker plugin.
This also means that every component MUST have a stylesheet, as other components are not processed.
You can check this behavior in your example.
dist-hydrate-script
to your output targets in the stencil.config.ts
outputTargets: [
{
type: 'dist',
esmLoaderPath: '../loader',
},
{
type: 'dist-hydrate-script',
},
...
}
tailwindHMR()
from plugins
npm run build
hydrate/index.js
The last css classes of FooterNav (footerNavCss)
.duration-300{transition-duration:.3s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}
With tailwindHMR()
/*!@.duration-300*/.duration-300.sc-footer-nav{transition-duration:.3s}/*!@.ease-in-out*/.ease-in-out.sc-footer-nav{transition-timing-function:cubic-bezier(.4,0,.2,1)}@media (min-width:1024px){.lg\\:flex-row{flex-direction:row}.lg\\:gap-4{gap:1rem}.lg\\:rounded-md{border-radius:.375rem}}
You can see that
lg:
, hover:
, , etc)I guess the best way would be to do the required part (as we do in our plugin) in the css transform
plugin phase. Because most worker plugins run directyl afterwards.
From StencilJS source code, as far as i understand it:
Thanks for the context - great find đ
One of those lovely side-effects đŠī¸
The TW plugin runs in beforePlugins
because it needs the raw sources to process the tsx
source. The other plugin entry points don't give the tsx
source, only the css
source (it's been a while so would need to check this properly again). At the start I didn't have a mapping between the inline styles and the associated css, but had to build something like that for the all the other funny stuff going on.
But thanks for the updates
Yeah, just checked again - as soon as you use a pluginType
of anything, you only get css files:
pluginType: 'sadsad'
The files passed in:
dep: C:/git/stencil-tailwind-plugin-example/src/components/hero-section/hero-section.css
dep: C:/git/stencil-tailwind-plugin-example/src/components/demo-section/demo-section.css
dep: C:/git/stencil-tailwind-plugin-example/src/components/demo-card/demo-card.css
dep: C:/git/stencil-tailwind-plugin-example/src/components/footer-nav/footer-nav.css
dep: C:/git/stencil-tailwind-plugin-example/src/components/main-app/main-app.css
dep: C:/git/stencil-tailwind-plugin-example/src/components/top-nav-bar/top-nav-bar.css
I remember been disappointed that you couldn't get tsx
files ... but still if the HMR "works", just need to check if you run it twice if you start getting duplications or not ... then could just have a "hydrate" plugin, but with the same underlying workings đ¤
I had the same discovery as you. Stencil only checks if a pluginType
is set. If so, it adds the plugin as a userPlugin
, which are css transformation plugins... Very disappointing.
I checked the tailwindcss
sourcecode while developing our plugin variant and they load the content (`--contents flag or from your tailwind configuration) manually. See: https://github.com/tailwindlabs/tailwindcss/blob/a92932f4cc3c071334cfaa2b4a782419bdfe83e5/src/cli/build/plugin.js#L179
So i did the same with our plugin. This works for our best practice; does not work if css and tsx filenames differ.
const tsxFilename = filename.replace('.css', '.tsx');
let changedContent: any[] = [];
const exists = !!(await fs.stat(tsxFilename).catch(() => false));
if (exists) {
changedContent = [{ content: await fs.readFile(path.resolve(tsxFilename), 'utf8'), extension: 'tsx' }];
} else {
...
}
const tailwindPlugin = makeTailwindPlugin(conf.tailwindConf, changedContent);
If using the same logic as tailwindcss (fastglob) is possible, it should also work generically with the tailwind configuration the user provided.
This would mean no tsx source is required by Stencil. It can all be done in the css path like the tailwindcss cli does it.
Unfortunately there are also cases where the style components are conditional, which means a component can have more than 1 stylesheet associated and the inline styles need to be added to each one.
Going to re-open this open to track - the HMR plugin works but the amount of css that is injected is actually quite high, which is "workable" for dev but for a proper component, probably not so great.
As this plugin is a rollup plugin (no pluginType: 'css'), this is run AFTER the stencil hydrate plugin is run.
The problem:
Stencil hydrate adds comments to the css classes so the scoped classes can later be rewritten to work hydrated component again.
Now with this plugin, all tailwind inline-classes and utility classes, which generate more classes (
:hover
,lg:, md:
and so on) are added AFTER the comments for the hydrate package have been created. Resulting in broken styles with SSR.We have created our own plugin thanks to your source code (and searching the tailwindcss source) which runs as a
css
plugin, fully creating all css classes BEFORE any Stencil plugin runs.One drawback is that we need to load the tsx file manually (like tailwindcss does with changedContent) and don't have any _sourceTsx already set (has same content as sourceCss), as the plugin is run only on css files.
Thanks for all your hard work.