SSR via Puppeteer

What do you guys think about this approach?

It looks easy and works with anything JS based, including Elm.


I think my biggest concern with SSR in Elm and what is mentioned in the article is the-hydration. There are any number of ways to render static html from JS on the server. ( I do think puppeteer is a great option though!). However, if Elm does not have a way to re-hydrate with out completely wiping the work that was already done then React SSR will always win out.

1 Like

I can see a way this can be done, but have never tried it out. It would work as follows:

Write encoder + decoder for the Model.
Do SSR for the Elm app. Also include the encoded Model in the static HTML that is output.
Pass in the encoded Model as a flag when starting the Elm application client side.
Start from that Model state on the first rendering of the Elm application client side.

Will it work?

I would have to look into it, but no I don’t think so. Based on what I know of the Browsermodule and Elm programs it’s first step is to wipe DOM and render regardless of passed in state. On application it is the whole dom and on everything else (except watcher) it is everything in the passed in dom element.

The init function takes flags as an argument, and builds the first Model to be rendered from it:

init : flags -> ( model, Cmd msg )

Browser.element has a quirk right now where it will diff the node you give it rather than wiping everything out, if you use it with the model encoder/decoder you can rehydrate that way.

I meant to get further on it but I haven’t had time recently, the last piece I wanted to try was writing out the model in the server side render and having Elm start with it without having to write an encoder/decoder for the whole model.

On thing to note is that the rehydration doesn’t work in debug mode, it wipes the node in debug!

Exactly, but the entire dom is still re-rendered based on that first state even if the SSR generated dom is the exact same as what would be generated from that state. That is what I am referring to when I say re-hydrate. I could be wrong, but I believe in React they are able to instantiate React based on SSR’d React without doing any re-painting or re-rendering of the SSR’d dom

Yes, although it sounds like Browser.element may by a quirk be able to diff against the DOM that was statically rendered. Rehydration is definitely not a supported feature of Elm yet, and it will in many cases wipe the DOM and re-paint it.

The re-painting will typically lead to the entire page blinking as the client app takes over. This can be avoided by having Elm draw into a DOM that is not shown and then swap it in on the animation frame. It won’t be super quick since its a full paint and not a diff, but at least the blink can be avoided.

There is an Ellie showing how to do this, but I can’t find the link for it.

1 Like

Yeah! I think for me I love Elm for what it is capable of doing now and what is supported in Core, and I am looking forward to when other features like SSR come in the future so I can use Elm even more, but there is nothing wrong with using different tools for different needs. :slight_smile: SSR is needed for marketing and content sites, but for an application where the pages are locked by Auth anyway it doesn’t matter and Elm is definitely the choice I will make for that

I wonder if websites like youtube or facebook use the hydration technique. Most of these website send out a page with placeholders like this:

1 Like

As I understand it Google will already render your site before indexing, so not needed if all you want to do is appear in the Google index.

But for sharing urls on social networks, SSR is important. Facebook or Tweeter crawlers do not support JS, so you need plain HTML to have a nice preview.

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.