I’m building an single-page, progressive web, todo app in Elm (code, demo). Because the PWA features are not available inside Elm, I need to embed the compiled JS into custom HTML alongside some more JS setup (e. g. for the service worker).
I’ve noticed that when loading the app, it quickly flashes the disclaimer about JS not being available before Elm kicks in. However, I think that some while back, when reloading the page, it didn’t appear, so maybe I introduced the flash when adding PWA features. But I know that in Elm Reactor there is absolutely no flash.
Playing around with where I put the compiled Elm code (e. g. separate JS file, embedded into HTML like Elm Reactor) did not give me much insight to what’s happening. I’m unsure whether this is due to the service worker, other Elm-external tech I used, or if there is a better way of including the Elm code so that this does not happen.
Do you have any pointers on how to integrate the Elm code more tightly to prevent the flash?
Wow, that actually seems to have worked. I was sceptical at first, but I think I understand what’s going on.
However, I just tried <noscript> and when I refresh the page, there is no flash. So my guess is that the browsers eagerly try to paint, unless there is nothing to paint. With a <noscript>, the browser correctly determines that there is nothing of interest to paint and so seems to wait until Elm populates the DOM with something paintable. That’s my theory at least.
So thanks a lot for your response! Maybe someone knows more about this issue and can check my theory or provide more details.
There are certain things that will block rendering in the browser. Two common ones are scripts in <head> and an external stylesheet linked with <link rel="stylesheet">. Your application does not link a stylesheet (that I could find looking at index.html), so the rendering does not block. Instead, styles come in as interleaved <style> tags, I guess from elm-css or similar. Thus, any content in index.html will paint as soon as the html comes in. Putting it in <noscript> makes the intent about “no JS available” explicit.
Not blocking the browser and allowing it to paint as soon as it has data is typically a good thing! One common optimisation is to inline the CSS that will be used for that page only in the <head>, and load the rest lazily. If your styles are rendered from the script, you get part of this built-in.
Playing with eager paints
In the case of client-only applications (i.e. ones that need the script to come in so that it can render), it seems nice to me to have a minimal placeholder while the app loads. I tend to avoid text, and rather try to match what the general UI (navigation, content, colours) will look like once the script has rendered. The UI that you have linked is pretty minimal right now, but I think it would be fun to try this once it is more settled. For instance, you might have another “flash” if your app has a background other than white, since the browser will render with white first, then swap.