The setup
I had a really simple app which didn’t really need the new navigation, but I decided to implement it anyway as a learning opportunity before I do something similar at work.
On my laptop I use elm-live so that my app is available under /
. Then I compile it and deploy on GitHub Pages and it’s available under /random-color
.
Letting Route.fromUrl
know about the mount path
AKA having the same URL parser for both mount path.
Skipping all the problems related to deploying SPAs on GitHub Pages, the first problem I ran into is that the URL parser had to know what path the app root is mounted under (later called “mount path”) so that it can skip it when translating a string to a route. That was pretty easy to solve: I passed the mount path through flags and then just passed it whenever I had to call Route.fromUrl
(I based my navigation code on elm-spa-example hence Route.fromUrl
).
Including the mount path in the links
The bigger problem is including the mount path in the URLs in the app. I think most other frontend libraries and frameworks solve this problem by not using the <a>
tag directly but rather some kind of a wrapper which knows about the mount path and can include it in the links generated in the app.
In Elm it would mean passing some kind of a link function to each view function. In a small app that’s not a problem but I can imagine it can get cumbersome in a bigger app.
So then I thought about just adding the mount path in the handler for internal URL requests. That kinda works but then the links on the page don’t point to the correct path by themselves which can break “Open in new tab”.
How else would you solve that problem?
The solutions I was able to come up with:
- A link function that I mentioned.
- Something similar is proposed as a solution in How do I manage URL from a
Browser.element
?. However, thelink
function there doesn’t need information from the model, so using it deep down in some view function isn’t a problem. - If absolutely necessary, the
link
function could have the mount path hardcoded and then that path could be changed on production just before the compilation step.
- Something similar is proposed as a solution in How do I manage URL from a
- A web component which is just a simple wrapper over
<a>
and knows about the mount path.- If I absolutely had to solve this problem, then I’d probably go with that, but for simpler apps I’d love to have a more straightforward solution.
- Mounting it under the same path both on dev and production.
- Seems straightforward, adds some troubles around dev setup. In this scenario, I’d probably still write a “static”
link
function which includes the mount path so that it can be easily changed if needed.
- Seems straightforward, adds some troubles around dev setup. In this scenario, I’d probably still write a “static”
- Use hash navigation. All links in the app can then just start with a hash (
<a href="#foo">
) and the problem with knowing the mount path disappears since you’re not really changing the path in the browser but just the hash part.- elm-spa-example does this, but if possible I’d like to avoid doing that.