Hacker News new | ask | show | jobs
by corny 895 days ago
I'm not happy with any of the solutions to prevent a flash of undefined components. Has anyone given up on web components for that reason? Or is there a best practice for this?
7 comments

Sounds like you might like the idea coined as "HTML Web Components": https://blog.jim-nielsen.com/2023/html-web-components/

You basically write all the normal HTML and CSS so it's loaded in right away. But then you also make use of the advantages that defining a custom element gives you.

That's a nice workaround but still just a bandaid in my opinion. Instead of a "flash of undefined component" you get a flash of whatever the vanilla html is before your web component was loaded. Now you have to adjust the vanilla html to look as close to your web component as possible, at which point you may just want to use vanilla html and css altogether and ditch the web component.
Use a loading overlay that will show for 0.25 seconds if you're that concerned about this
User delays of 100-300 ms is perceptible to the user. This is the exact issue we want to avoid.
And in that delay they'll see a loading screen
Yes, this technique sounds really good. Thanks for this.
You're welcome!

I've started moving to this technique from my earlier technique of putting a data-module on wrapping div components, where I manually had to deal with a bunch of stuff which HTML Web Components just do for you for free. Super handy!

How do we write this? I googled some tutorial and it seems it is still JS under the hood
It's basically just web components without the ShadowDOM implementation. I do it in some projects, but it comes with other drawbacks too.
Yeah like no slots.
Nested components are not playing nice with their lifecycles too.

Querying elements also becomes more complex.

That article makes a helpful distinction, thanks!
the doc site doesn't have this problem because it doesn't make a giant single archive of code that loads slowly on a single core. lighthouse doesn't even record the flash. most of the pages are getting 98/99 performance scores.

i'm sure if you webpack the crap out of it bundling hundreds of dependencies into the same parse, it'll perform poorly, but well, stop doing that.

It definitely does have this problem, on Firefox at least. Refreshing the page has a lot of layout shift as buttons render.
I did. I can't accept that as a user, so I'm not going to make my users put up with it. The simplest "fade" solution or adding a loading dialog is a huge pain and I'd rather write vanilla html/css/js if it will allow me to avoid that.
I usually hide the web components until they are defined using `:not(:defined)` CSS selector
That causes CLS which is also an issue
My apologies. By 'hide', I meant hide visually (through `opacity: 0`) that keeps the space reserved to avoid CLS.
Do I understand correctly, this only works when the size of the component is determined from "above" in the layout tree? That sounds not generally useful...
This is a solved problem.

You tackle it by doing two things:

1) use a bundler (rollup or webpack) if your code is big so it can be chunked and loaded quickly

2) have a loading spinner by default

Some developers have a dogmatic zeal against loading spinners, but users are very accustomed to them.

In fact, it's possible for websites to load _too_ fast, seeming unnatural to users (who at this point in time are very much expecting the flow to be request->spinner->load).

Do webcomponents not have build time pre-rendering or SSR?
Web Components in general: sure. But what Shoelace uses: no.

Specifically, Shoelace uses Shadow DOM and adoptedStyleSheets.

For Shadow DOM, there’s Declarative Shadow DOM, a way of serialising a Shadow DOM, which is extra work to support, but possible; it’s currently supported in Chromium and Safari, and last month Firefox landed an experimental implementation.

But the key feature and problem of Shadow DOM (in my opinion, more problem than feature) is how it isolates styles. You need to add the stylesheet to every shadow root, via a <style> or <link rel=stylesheet> element (and hope the browser is clever enough to deduplicate, which it should be in the latter case but I don’t think it will be in the former), or via adoptedStyleSheets, which is generally more efficient and allows shared mutation after construction (unlike the other approaches). Shoelace uses adoptedStyleSheets. Trouble is, that doesn’t work with Declarative Shadow DOM.

No, I believe it is the nature of web components that they can't be server rendered. I'm not talking about framework components like react, vue, etc.
Certainly can just depends on the framework used. I know 11ty can server render them. Astro.build supports lit as well.
Give me declarative adopted stylesheets!