I know there is a Project to implement an Elm SPA.
But I have not bothered with it when I started working on my own SPA and simply used Browser.application
to write my own approach to developing Elm SPA.
I wanted to share this approach here, since it might be of interest and different to Elm SPA.
My SPA is Open Source and you can inspect it’s entire Codebase here: Demnet/ui - OAuth
A Datatype based SPA
At the center of my SPA sit the Datatypes handled by the SPA.
In my src
folder I have a folder called DemNet
(that’s the project’s name) where I have 1 Module for each Data Type handled by the SPA.
Each Module exposes a Type, a decoder
and an encode
function.
As well as values otherwise relevant for the Data Type.
The Cache
All of these Types are used by the src/DemNet/Cache.elm
Module, which takes all of these types and creates a Cache for each.
type alias Cache =
{ users : Dict Username User
, languages : Dict Lang Language
, elections : Dict Int Election
, messages : Dict String Message
, drafts : Dict Int Message
}
Each Cache is just a dict from a type specific unique identifier (i.e. the username, the id, …)
to a value.
The Page
In the Page module, I can now, since the data shown on the page will be stored in the Cache
,
simply use the keys to the data I need in the Cache
to address them.
type Page
= Welcome
| Vote Election.Id
| Feed { pageNum : Int, pageSize : Int }
| Read Message.Id
| Write Message.Id
| Profile Username
| Error Int String
Instead of storing the state of the Page in the page, I only describe what should be in the Page and leave the rest to the Cache
.
The Model
In my Model
I thus now store the following two values:
type alias Model =
{ page : Page
, cache : Cache
, ...
}
And when I render this Model,
I first look at the page and then fetch the
data from the Cache that is referred to by the
page.
The Advantages
This approach has several advantages in my mind:
- Because the page, that is currently shown, has nothing to do with the data that is shown within it, I can modify a data entry, regardless of the currently viewed page. And I can change my page, regardless of whether or not I have the data required for this.
I do not throw out any messages inupdate
, because of an invalid page. - Because I keep a Cache of all the data that the client received, I can also work offline or with short network issues. Because every page you have visited before, is still in RAM (or localstorage if I ever store the cache there).
The Disadvantages
But I do not want to appear, as if this is the perfect or good way to write a SPA.
There are disadvantages:
- If the Cache is not regularly cleaned, RAM will be wasted and eventually small devices will have performance issues.
- Many more, that I cannot yet foresee, since this is not an approach that I have been running in Production for many months, but only just developed.
My best regards to all of you!
May this post have inspired you at least, to think about alternative ways of creating Single Page Applications.
If I have just reinvented a wheel, please let me know, so I may stop embarrassing myself and start to learn about where this approach was/is used and why.