Lately there has been some interesting discussion about Modern Web.
I personally think that
- Single Page Applications (SPAs) have been (ab)used in places where a more traditional server side approach could have been a better fit
- SPAs require extra care (navigation, scrolling, accessibility, SEO, etc.)
- There are many SPAs that are not well crafted but when they are well made, SPAs can very much enhance the user experience
- The browser feels like the natural place where to handle complex UIs, not the Server
- As developers, I (we?) like to keep using my best tools to improve the Developer Experience
Related to the last point I feel that the Elm language come with a curse:
"Once you are in Elm, you want to stay in Elm"
This is not happening only with Elm, but with any compiled-strictyly-typed-inferred-immutable-purely-functional-with-nice-errors language.
So to alleviate some of these issues I made a small script to convert Elm SPAs into Statically Generated Progressive Web Applications (PWAs), called elm-starter
.
(Yes, another one)
Goal
The goal is to have a tool that
- Is mainly written in Elm (see the curse mentioned above)
- Supports the majority of Elm libraries (elm-ui, elm-spa, etc.)
- Relatively simple to use
- Can be used to bootstrap a new app or to convert an existing one
- Is not invasive and can be removed at any time
The resulting PWA should have these characteristics
- Works without Javascript
- Works off-line
- Is installable on mobile/desktop
- Is friendly to bots (SEO)
- Supports preview cards
- Renders fast (gets high scores in Lighthouse)
The classic Lighthouse screenshot with confetti 🎉
Preview cards in Slack:
What does this tool do?
- Generates all the needed files for a PWA
- Centralize in one "single-source-of-truth" all metadata
- Generates static pages
This is all. Quite simple!
Demos
There are 3 demos made with elm-starter
:
1. The official elm-starter
demo
This is a simple SPA with an SVG object. It is an example of one of the differences between SPA and MPA: page transition. This app works both with and without Javascript. The only difference is that: No Javascript -> No page transition.
Note that the page transition is made with CSS transition applied to SVG. I realized too late that this is only supported in Chrome and I didn't have the time to change it, but you get the picture.
Here is the difference between having Javascript ON or OFF:
2. Todo MVC
This is the classic Todo MVC, the one that I used extensively to compare different frameworks in a past article.
It was originally coded by Evan Czaplicki, I just adjusted it to fix some accessibility issues.
Compared to the previous demo, this one doesn't work without Javascript for its nature.
The preview card on Slack:
3. elm-spa
Example
This example shows a possible synergy between elm-spa, a nice way to create complex SPAs that take care of several things for you through automatic Elm code generation. For example, to create new pages you simply run a command in the terminal and this creates the right files, routes and logic for you.
elm-starter
can then take over and transform it in a PWA, statically generating all routes.
In this specific example all pages are accessible without Javascript, but the widget that requires Javascript (like the counters) will not be working.
The preview card on Slack:
Behind the scenes
-
All files are generated by Elm code:
-
HTML: Generated using a modified version of zwilias/elm-html-string. For example Index.elm generates
index.html
. -
JSON: Generated using elm/json. For example Manifest.elm generates
manifest.json
. -
CSS: Generated from strings. I know, this is not ideal. rtfeldman/elm-css, that is CSS with the type-safety of Elm, seems not exposing the
toString
converter. The quantity of CSS necessary inelm-starter
is very small anyway so I kept it as a string. For example SnippetCss.elm. -
Javascript: Generated from strings. Again, the quantity of Javascript needed to run the App is minimal so I made the trade-off of saving it as string. For a larger amount of Javascript it is better to keep it in
.js
files. For example SnippetJavascript.elm.
-
HTML: Generated using a modified version of zwilias/elm-html-string. For example Index.elm generates
All static pages and snapshots are generated using Puppeteer.
Most of the CSS and Javascript is formatted "comma-leading" or "semicolon-leading" (sorry, I could not resist, see the Elm curse above, again)
This is a snapshot of Index.elm that generates index.html
:
SEO
Each page is statically generated with specific meta-tags so that search engine spiders can easily pick it up, also when they are not as sophisticated as Google, that is able to execute Javascript since a long time ago.
Someone says that even if Google can run Javascript, it still prefers static websites.
This is how Google indexed the elm-starter
demo after few days from its launch:
Similar projects
These are other excellent projects that can be used to bootstrap an Elm application or to generate a static site:
About Modern Web vs. Traditional Web
To get more insights about the debate mentioned at the beginning of this post:
- The disadvantages of single page applications by Adam Silver
- Developing a Javascript-free frontend by Matt Reyer
- The Return of the 90s Web by Max Böck
- Server-Side Rendering is a Thiel Truth by Tim Ruffles
- The Architecture No One Needs by Greg Navis
- Why I hate your Single Page App by Stefan Tilkov
- Second-guessing the modern web by Tom MacWright
- In defense of the modern web by Rich Harris
- “The Modern Web” by Chris Coyier
How to use elm-starter
You can find elm-starter
at github.com/lucamug/elm-starter.
The fastest way to start using it is by clicking this button:
This will automatically
- Create a repository containing
elm-starter
into your Github account - Deploy it live using your Netlify account
To modify the app simply clone the new repo on your computer and run:
$ npm install
$ npm start
Now you can edit src/Main.elm
and, after confirming the result at http://localhost:8000, commit your modifications to Github.
The new app will be published live automatically by Netlify in seconds, including re-generating all static pages.
More information available in the README.
This is all, thank you for reading! ❤️
Cover image: Mount Fuji seen from Kawaguchi lake by WorldInMyEyes from Pixabay
Top comments (3)
Good stuff mate. Going to be helpful for a lot of those who are dipping their toes on Elm.
I've also come across Mint which is competing with Elm for the "dedicated SPA language" spot. Personally, I prefer Mint's syntax.
Mint definitely fits more if you're uncomfortable switching away from the C style of syntax. Having been building web sites for 2 decades now, for me, Elm has been amazing to have. But, it's not for everyone and that's cool too.