Server Side Rendering with Elm

Lucamug
Lucamug
Jul 23, 2017 · 3 min read

I know that the good Evan is going to release soon the version 0.19 that probably will implement the server side rendering.

Nonetheless I want to try a little experiment with one of the SPA that I am working on.

As suggested by this article I used the elm-static-package.

But before running the script I needed to change couple of things in main.elm.

I use Navigation.program instead of Html.program.

The Navigation.program is expecting

init : Navigation.Location -> ( Model, Cmd Msg )
view : Model -> Html Msg

But elm-static=package is expecting

view : Html Msg

So first I created an initLocation function that would create a location object:

initLocation : Navigation.Location
initLocation =
{ hash = ""
, host = "localhost:3000"
, hostname = "localhost"
, href = "http://localhost:3000/"
, origin = "http://localhost:3000"
, password = "XXX"
, pathname = "/"
, port_ = "3000"
, protocol = "http:"
, search = ""
, username = "XXX"
}

Then I created a function that return the model:

initModel : Navigation.Location -> Model
initModel location =
...

Then I rename the view to initView

initView : Model -> Html Msg
initView model =
...

My original init function is now

init : Navigation.Location -> ( Model, Cmd Msg )
init location =
( (initModel location), (initCmd location) )

So my main function is

main : Program Never Model Msg
main =
Navigation.program Types.UrlChange
{ init = init
, view = initView
, update = update
, subscriptions = (\_ -> Sub.none)
}

At this point the function view, that is the one used by default by the package elm-static-html, is like:

view : Html Msg
view =
initView (initModel initLocation)

Perfect! Exactly the signature that we needed. A view that would just return Html Msg

There is still a problem. Running elm-static-html, Elm complain that the document.location doesn’t exists. Because in Node it actually doesn’t exists. If I remove the main function the problem disappear. But the app will not be functional. As a dirty fix I added these few lines inside node_modules/elm-static-html/index.js:

global.document = global.document || {};
global.document.location = global.document.location || {
hash: "",
host: "localhost:3000",
hostname: "localhost",
href: "http://localhost:3000/",
origin: "http://localhost:3000",
pathname: "/",
port: "3000",
protocol: "http:",
search: "",
};

Now the html is generated properly.

Now the complicated part is to embed this html in the pages and make Elm to activate and overwrite this html from the client side.

From here there are several option. One is what is called hydration that would let Elm to plug its virtual DOM in the existing html.

Another is to just replace the html page with the one created by Elm.

A third possibility, in case you are Server Side Rendering for SEO purpose, is to detect Googlebot and give it the rendered page while server the SPA version to human users.

If you are interested in Server Side Rendering you may be also interested in

More From Medium

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade