Experiments in Elm
This post is part of a mini series based on some of the experiments we’ve been doing at NoRedInk. A lot of these ideas are proof of concepts that aren’t intended to go anywhere. The focus is on experimentation and trying new things out! The majority of these posts will be about Elm.
Static site generation
In this post, we’re going to talk about static site generation. Jekyll? I’d rather use Elm! With elm-static-site
, doing this is trivial.
Imagine we have a blog. On our blog, we have multiple bloggers, which we have in a list like this -
-- Blog/Bloggers.elm
module Blog.Bloggers where
type alias Blogger =
{ name : String
, age : Int
}
noah =
{ name = "Noah"
, age = 23
}
dave =
{ name = "Dave"
, age = 33
}
bloggers : List Blogger
bloggers =
[ noah
, dave
]
Great. Now let’s make a statically generated page to list our bloggers.
-- Blog/Index.elm
module Blog.Index where
import Html exposing (..)
import Blog.Bloggers exposing (..)
bloggerView : Blogger -> Html.Html
bloggerView blogger =
div
[ id blogger.name]
[ text "Hello, my name is "
, text blogger.name
, text " and I'm "
, text (toString blogger.age)
, " years old!"
]
view =
div
[]
(List.map bloggerView bloggers)
This will generate a page like this
<div>
<div id="Noah">
Hello, my name is Noah and I'm 23 years old!
</div>
<div id="Dave">
Hello, my name is Dave and I'm 33 years old!
</div>
</div>
For every file in the folder you give it, it will take that file, and if it has a view : Html
function, it will take that out and turn into it a static page instead. So let’s say we had this structure:
examples/
Index.elm -- has a view : Html
Blog/
Index.elm -- has a view : Html
Bloggers.elm -- doesn't have a view : Html
the following files will be generated
output/
index.html
blog/
index.html
Notice that Bloggers.elm
gets skipped as it doesn’t expose a top-level view
function.
The way this script works is pretty simple really. It uses a script to convert the output of the view
functions to strings, and then through node, we extract the value from those ports to write to files with the same name as the module. This is why Blog.Index
gets turned into blog/index.html
.
Some background
Elm’s virtual dom is based on an implementation of a virtual dom simply called virtual-dom. How many times can we say virtual-dom in a sentence and have it still make sense?
This virtual-dom implementation has some cool libraries based around it, including one called vdom-to-html
. What this does is render the virtual dom to HTML, either on the client or one the server. It just takes a Node, then returns the HTML version of that Node as a string. In Elm, the type signature for that function just looks like this
toHtml : VirtualDom.Node -> String
Right off the bat, that will work with the majority of Elm views. For example,
view =
div
[]
[ text "Hello world!" ]
htmlVersion =
toHtml view
generates
<div>Hello world!</div>
and that’s it! Now we have static site generation in Elm!
If you want check this out, go to elm-static-site
and start using it! There’s plenty of ways to improve it, so if you want to ask just ask me at @eeue56 on twitter or eeue56 on Slack!