fix: css-only hydration to prevent FOUC (#991)#4856
Conversation
|
This is cool. Do we want to try to tackle the components that should be |
|
@driskull yeah, for sure. I didn't totally understand all the calcite hydrated hidden stuff, so I left it as is, but could absolutely just remove the |
Yep, that would be ideal. We would just need to maintain a list/map of those components |
| @@ -0,0 +1,15 @@ | |||
| const fs = require("fs"); | |||
There was a problem hiding this comment.
@paulcpederson can you use...
import fs from "fs";
import path from "path";
So we get some type safety?
There was a problem hiding this comment.
I think we'd have to update our package here :. Related to #4700 (comment)
There was a problem hiding this comment.
I tried that and got thrown an error about using import outside a module?
There was a problem hiding this comment.
ooooh, ok that makes sense, I can make that change once that pr goes in.
| (async function () { | ||
| const stylePath = path.normalize(`${__dirname}/../src/assets/styles/_hydration.scss`); | ||
| const components = await fs.promises.readdir(path.normalize(`${__dirname}/../src/components/`)); | ||
| const selectors = components.map((component) => `calcite-${component}:not([calcite-hydrated])`); |
There was a problem hiding this comment.
Something like this would be nice...
const hiddenComponents = new Set<string>(["alert", "input-message", "popover", "tooltip", "tree-item"]);
(async function () {
const stylePath = path.normalize(`${__dirname}/../src/assets/styles/_hydration.scss`);
const components = await fs.promises.readdir(path.normalize(`${__dirname}/../src/components/`));
const selectors = components.map((component) => `calcite-${component}:not([calcite-hydrated])`);
const selectors = components
.filter((component) => !hiddenComponents.has(component))
.map((component) => `calcite-${component}:not([calcite-hydrated])`);There was a problem hiding this comment.
this would flash unstyled content prior to javascript running
|
@driskull So after playing with this a bit, even a raw selector like |
driskull
left a comment
There was a problem hiding this comment.
@paulcpederson I'm still seeing some modifications on OSX.
diff --git a/src/assets/styles/_hydration.scss b/src/assets/styles/_hydration.scss
index 889c140f0cfc3a198e2c44823b304f523d1939c2..8685c9fe6e945e9b8af25fe029255019cdf1605c 100644
--- a/src/assets/styles/_hydration.scss
+++ b/src/assets/styles/_hydration.scss
@@ -11,6 +11,45 @@ calcite-avatar:not([calcite-hydrated]),
calcite-block:not([calcite-hydrated]),
calcite-block-section:not([calcite-hydrated]),
calcite-button:not([calcite-hydrated]),
+calcite-calcite-accordion:not([calcite-hydrated]),
+calcite-calcite-action-menu:not([calcite-hydrated]),
+calcite-calcite-alert:not([calcite-hydrated]),
+calcite-calcite-block-section:not([calcite-hydrated]),
+calcite-calcite-button:not([calcite-hydrated]),
+calcite-calcite-chip:not([calcite-hydrated]),
+calcite-calcite-color:not([calcite-hydrated]),
+calcite-calcite-color-picker:not([calcite-hydrated]),
+calcite-calcite-combobox:not([calcite-hydrated]),
+calcite-calcite-date-picker:not([calcite-hydrated]),
+calcite-calcite-dropdown:not([calcite-hydrated]),
+calcite-calcite-dropdown-group:not([calcite-hydrated]),
+calcite-calcite-fab:not([calcite-hydrated]),
+calcite-calcite-graph:not([calcite-hydrated]),
+calcite-calcite-icon:not([calcite-hydrated]),
+calcite-calcite-input:not([calcite-hydrated]),
+calcite-calcite-input-date-picker:not([calcite-hydrated]),
+calcite-calcite-input-message:not([calcite-hydrated]),
+calcite-calcite-label:not([calcite-hydrated]),
+calcite-calcite-list:not([calcite-hydrated]),
+calcite-calcite-list-item:not([calcite-hydrated]),
+calcite-calcite-modal:not([calcite-hydrated]),
+calcite-calcite-pagination:not([calcite-hydrated]),
+calcite-calcite-panel:not([calcite-hydrated]),
+calcite-calcite-pick-list:not([calcite-hydrated]),
+calcite-calcite-popover:not([calcite-hydrated]),
+calcite-calcite-popover-manager:not([calcite-hydrated]),
+calcite-calcite-radio-group:not([calcite-hydrated]),
+calcite-calcite-shell:not([calcite-hydrated]),
+calcite-calcite-shell-panel:not([calcite-hydrated]),
+calcite-calcite-stepper:not([calcite-hydrated]),
+calcite-calcite-tab:not([calcite-hydrated]),
+calcite-calcite-tabs:not([calcite-hydrated]),
+calcite-calcite-tile-select:not([calcite-hydrated]),
+calcite-calcite-tile-select-group:not([calcite-hydrated]),
+calcite-calcite-tooltip-manager:not([calcite-hydrated]),
+calcite-calcite-tree:not([calcite-hydrated]),
+calcite-calcite-tree-item:not([calcite-hydrated]),
+calcite-calcite-value-list:not([calcite-hydrated]),
calcite-card:not([calcite-hydrated]),
calcite-checkbox:not([calcite-hydrated]),
calcite-chip:not([calcite-hydrated]),
@@ -27,6 +66,7 @@ calcite-date-picker-month-header:not([calcite-hydrated]),
calcite-dropdown:not([calcite-hydrated]),
calcite-dropdown-group:not([calcite-hydrated]),
calcite-dropdown-item:not([calcite-hydrated]),
+calcite-dropdown-menu:not([calcite-hydrated]),
calcite-fab:not([calcite-hydrated]),
calcite-filter:not([calcite-hydrated]),
calcite-flow:not([calcite-hydrated]),
@@ -88,8 +128,9 @@ calcite-tooltip:not([calcite-hydrated]),
calcite-tooltip-manager:not([calcite-hydrated]),
calcite-tree:not([calcite-hydrated]),
calcite-tree-item:not([calcite-hydrated]),
+calcite-utils:not([calcite-hydrated]),
calcite-value-list:not([calcite-hydrated]),
calcite-value-list-item:not([calcite-hydrated]) {
visibility: hidden;
pointer-events: none;
-}
+}
\ No newline at end of file|
Maybe we could use the docs:json or stats to generate the styles? https://stenciljs.com/docs/docs-json |
This would be great, but but it would require 2 builds. Let's proceed with the current approach and we can revisit later if we notice any funkiness. 🎶🎸🎶 |
|
@driskull going to experiment with using a custom target, if that requires two builds I can just add a filter for these old folders |
|
Should we gitignore the generated scss file? Seems like the sass files in our project are not distributed as part of a release, so shouldn't be an issue to ignore it as it's generated each build anyways. |
|
Good question. I think we can ignore it. |
jcfranco
left a comment
There was a problem hiding this comment.
🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘
🤘🎸🎸🎸🎸🤘🎸🤘🤘🤘🤘🤘🎸🤘🎸🎸🎸🎸🤘🤘🎸🎸🎸🤘🤘🎸🎸🤘🤘🎸🤘🤘🤘🎸🤘🎸🎸🎸🎸🤘
🤘🎸🤘🤘🎸🤘🎸🤘🤘🤘🤘🤘🎸🤘🎸🤘🤘🤘🤘🎸🤘🤘🤘🤘🎸🤘🤘🎸🤘🎸🎸🤘🎸🎸🤘🎸🤘🤘🤘🤘
🤘🎸🎸🎸🎸🤘🎸🤘🤘🎸🤘🤘🎸🤘🎸🎸🎸🤘🤘🤘🎸🎸🤘🤘🎸🤘🤘🎸🤘🎸🤘🎸🤘🎸🤘🎸🎸🎸🤘🤘
🤘🎸🤘🤘🎸🤘🎸🤘🎸🤘🎸🤘🎸🤘🎸🤘🤘🤘🤘🤘🤘🤘🎸🤘🎸🤘🤘🎸🤘🎸🤘🤘🤘🎸🤘🎸🤘🤘🤘🤘
🤘🎸🤘🤘🎸🤘🤘🎸🤘🤘🤘🎸🤘🤘🎸🎸🎸🎸🤘🎸🎸🎸🤘🤘🤘🎸🎸🤘🤘🎸🤘🤘🤘🎸🤘🎸🎸🎸🎸🤘
🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘🤘
| }); | ||
| const selectors = components | ||
| .filter((entry) => entry.isDirectory()) | ||
| .filter((entry) => entry.isDirectory() && !entry.name.includes("calcite-")) |
There was a problem hiding this comment.
Nitpick: I don't think we need this. There shouldn't be any calcite-prefixed folders anymore.
|
@driskull can you try this one more time? I've added a little heuristic to filter out non-component files and folders, so I think this should be pretty accurate now, even for devs with older cached directories |
Related Issue: #991
(see also #620, #609)
Summary
Because stencil's hydration styles are applied via JavaScript, there is a time before the JavaScript has run where you can see the slotted content flash in before the component is rendered.
A few releases ago stencil allowed you to turn off their hydrated styles entirely via the
invisiblePrehydrationconfig flag. This pull request opts out of the injected styles and generates a set of styles for all our components so that they are invisible if they are not hydrated. Because these styles are then in the global css file, they will apply to the page even prior to stencil's loader running at all, ensuring that the FOUC is removed.There may be a better way to generate this list of components, but currently just reading the components directory and adding a style for each one.