As I’m nearing the elm-pages v3 release, I’m building a few examples to showcase some of the new features. Since elm-spa-example is the canonical Elm app, I went ahead and created a version of that with elm-pages.
I wanted to keep the functionality as similar as possible to the elm-spa-example and realworld spec, so I refrained from adding some of the things that elm-pages is best at, like pending/optimistic UI, adding meta tags using resolved data for a given route, doing dynamic client-side validations, and directly making database queries in the data function. This is actually kind of cool in a way because it leaves those features as an exercise with the baseline being more simple. Might be the topic for a workshop exercise in the future or a video demo!
The only places where I deviated from the elm-spa-example behavior where places where writing idiomatic elm-pages server-rendered code would require me to make a change. For example, I used Forms whenever possible, including GET forms, which navigate to a URL with a query parameter when you submit them (this is how I handle pagination and tag filters). So the elm-spa-example doesn’t use URL query params to manage this, but I made this slight change here. I prefer this because it makes these URLs sharable, but it also lets you leverage elm-pages form features to reduce the amount of work to wire things up.
A few things to notice:
None of the routes use Model, init, or update whatsoever!
There are no loading spinners - loading states are handled on the server (the data BackendTask’s are resolved before the initial page HTML is sent over). This often works out nicely because your server can make faster round-trips to fetch data since it’s in the same data center (as opposed to making round trips between the user’s Browser and your data center, which may be far apart). In the case of the realworld API that I’m hitting here, it’s pretty slow so this might not be ideal, but that’s the general idea. I might make a full-stack version of this demo that implements the backend as well - it turns out, this won’t be a lot more work than reaching out to an external API, and it will give us more control over the performance as well.
There’s a lot more to share about the upcoming elm-pages v3 release, so stay tuned! Feel free to share questions or feedback here, or join the #elm-pages channel in the Elm Slack. You can try out the v3 beta with this starter repo as well. Cheers!
In the context of elm pages v3, if you attempted to imitate blitz js, it would be impossible to use elm to actually fetch from a database directly ( or at least impossible without lamdera?). In that case, did I understand your explanation correctly - you are suggesting using server side API calls written in elm to fetch from a backend API?
I believe the speed is roughly the same, but the perceived slowness you are seeing is that the elm-spa version shows “Loading…” when it’s navigating back. The API responses aren’t cached in the elm-spa version either so there’s no difference with regard to caching API responses.
Really the idea with an elm-pages app is that you want to host your data and your elm-pages app in the same datacenter, and have quick data loads. In cases where there really is slow processing, you wouldn’t use the elm-pages Route Modules’ data to load up that data but would instead use the more traditional TEA approach of making an API request from init with elm/http. elm-pages allows you to use either approach, but you can simplify your code and take advantage of the features that elm-pages provides in cases where you can use that kind of architecture and resolve data in a performant way. So this application that hits a fairly slow API isn’t the best illustration of these features, but I think all the more reason that doing this with the backend implemented in elm-pages would be a really neat demo as well!
It’s actually very possible to fetch from the database directly with elm-pages v3! We’re running an Elm app in a Node context. You can imagine doing this through a port. elm-pages actually exposes something that uses a port in its generated code under the hood, but it gives you a nice abstraction for running it, BackendTask.Custom.run.
Yes, you have your standard Elm init, update, Model, and subscriptions, in addition to the things that elm-pages gives you, so you can do whatever you might be used to doing in a regular Elm application.
The framework also manages a lot of state for you, so the best practices with elm-pages v3 is to rely on this state instead of using your Model/update when possible. I think of it as building things declaratively rather than imperatively.
In the TodoMVC example I linked to above, there is optimistic UI which is all done through the form submission state that the framework manages for you (so the framework’s internal Model which it exposes through some high-level APIs). If you try out the UI you can see that it shows optimistic updates, it’s easier to see if you slow down requests in the network tab.
I could get really excited about a starter with postgres + flask rest + pages v3, that ran on render or something similar. That is essentially what I would like to train in, in the long run. I have to reflect on whether spa or server rendered will become more popular overall before I choose between elm-spa or similar and pages-v3.