If you haven’t used Elm before, it can be a bit intimidating to get started. A pure functional programming language for building web applications, Elm provides a number of tools for writing Elm apps, including
elm reactor for fast recompiling of specific modules and
Luckily, there are a number of options for setting up a successful Elm application today. Let’s explore what’s available for building an Elm application in 2022, including ways to get a better development environment, as well as the tooling surrounding Elm that makes working with the language as delightful as possible.
Elm (the language)
You can install the Elm language (and its bundled tooling) from npm. Installing Elm globally gives you access to a handful of useful tools:
This is the command line repl for Elm. You can use it to execute commands in Elm and see what the result would be.
package.json. If you want to add Elm to a project (or start a new project), you’ll need to run this command. When you do, you’ll see a message like this:
$ elm init Hello! Elm projects always start with an elm.json file. I can create them! Now you may be wondering, what will be in this file? How do I add Elm files to my project? How do I see it in the browser? How will my code grow? Do I need more directories? What about tests? Etc. Check out <https://elm-lang.org/0.19.1/init> for all the answers! Knowing all that, would you like me to create an elm.json file now? [Y/n]
This is an example of how Elm provides helpful information at every opportunity, as well! The link it provides takes you to documentation on how to structure and scaffold an Elm application.
As you may expect, this command installs an Elm dependency in your application. Sometimes you will need to install a dependency that is already a sub dependency, in which case Elm will inform you that it’s going to move the dependency up in the chain so that you can import its modules directly.
There are other commands available as well. Feel free to run
elm --help to see all the available commands and options.
There are a handful of plugins and extension for different editors, the majority of which can be found on an officially updated list within the Elm organization on Github. My editor of choice is VS Code, and the VS Code extension for Elm is an excellent tool for writing in Elm. It provides details on errors when saving, references to where a particular function or value is utilized, and access to function documentation on hover
elm-format. Similar to Prettier, this utility can be used to ensure that all Elm code matches the official style guide. Unlike Prettier, there is no custom configuration, meaning once again that your team can focus on writing code instead of what kind of quotes to use.
The Elm community has an unofficial linter (called
elm-review), which can be used to check your code for potential bugs or mistakes, or highlight a better way to write Elm. Unlike
elm-format (and more similar to tools like ESLint),
elm-review does not come with any default rules to follow:
All the rules describing problematic code are written in Elm, and elm-review does not come with any built-in rules; instead users are encouraged to write rules themselves and publish them as Elm packages, for everyone to benefit. Search the package registry to find what’s out there!
The de-facto standard for testing an Elm application is
elm-test. However, as noted in the README:
When people say “elm-test” they usually refer to either:
- This Elm package for writing tests.
- rtfeldman/node-test-runner – a CLI tool (called elm-test) for running tests defined using this package in the terminal.
The Elm package (available on the Elm package repository) contains the functions required to write tests, query HTML, and perform assertions. The syntax should be familiar if you’ve written unit or fuzz tests in other languages, with
describe blocks and individual
test functions being called.
To actually run the tests, however, there are currently two options. The first, as noted above, is
node-test-runner, which is available from npm at
elm-test. This utility will run the tests as defined in your Elm code, and return the results. There is a second option,
elm-test-rs, which is written in Rust instead of Node. It has a handful of features that
node-test-runner does not have, as well as some downsides (see the Github README for details), but in general both tools work very well for testing Elm code.
Now’s the fun part - writing our app! Using only the above tools, you would be set to build an Elm application that is properly formatted, tested, and compiled to JS. However, that doesn’t help you get it onto the page; you’l still have to create an HTML file, import your Elm code along with any other dependencies you may have, and test it in your “live” environment. Found an error? Time to recompile!
First on our list is elm-live. From their README, elm-live provides:
- Hot reloading
- Local SSL
- No reload mode
- No server mode
- and more!
.vue file? Go for it!
It turns out, we can! Elm has pretty good support across compilers/bundlers, so that you can import an Elm file directly into your core JS application - no compile step required! Keep in mind that you will still need to initialize the Elm application in order for that code to do anything, but otherwise you are able to treat it like any other compile-to-JS asset.
Here’s a list of common compiler options:
Great! Now we’re able to import our Elm code directly into our existing applications, making the integration that much easier. However, there’s still one last thing we can do to improve our environment. One problem we may run into is that the tooling described above needs to be installed locally in order to utilize it, which can lead to more work onboarding developers or getting started with a project.
There is a tool called
elm-tooling which does all the hard work for us. Rather than having to install the Elm language,
elm-test-rs) individually, we can run
npx elm-tooling install, and all of the core tooling can be installed at once, significantly faster than if they were installed individually. This can even be added as a postinstall command in your
package.json, ensuring that Elm and its related tools are available with a single install command. This is extremely useful when setting up your local environment, or during CI build steps.
Frameworks and Templates
All this tooling is great, and an excellent way to get writing Elm code and integrating it into your application. But sometimes it’s nice to start from a higher level abstraction, much like React developers often start with Create React App, or Vue developers use the Vue CLI. While there are no official templates or frameworks beyond what we’ve already talked about, there are a few interesting projects that are worth taking a look at.
Where elm-spa is targeting single-page applications, elm-pages is built for generating static sites. Utilizing Elm’s type system, elm-pages’s goal is to make handling external data for a static site easy. Conceptually, it’s similar to what Gatsby or Gridsome do (provide a typesafe interface to access multiple types of data), but utilizing Elm’s strengths rather than adding an additional type system such as GraphQL.
ElmBook’s goal is to provide a solid documentation site for library or package code. It includes a search function, as well as the ability to break down your docs into chapters and books. It also allows rendering Elm code within your docs, via a shared model, so that you can demonstrate functionality in the UI. It’s built on top of elm-live, so working with ElmBook should feel familiar if you’ve used it before.
If you’re coming from Vue, the focus of ElmBook is similar to Vuepress, but rather than focusing on markdown files, ElmBook is written within Elm itself. Markdown is supported for writing the documentation itself, but all of your work will be handled within the Elm code, making your documentation perfectly typesafe as well as useful.
Every application, tool or team has their own history worth telling.
ElmBook tries to help them by making it easy to create rich documents that showcase their libraries documentations, UI components, design tokens, or anything else their creativity comes up with.
This was a template I created to scratch my own itch. As a Vue developer, I love working with Vite, and really wanted a base template for Vite that I could use to build Elm applications.
vite-elm-template is a basic Vite template intended to get you started writing in Elm without having to spend time configuring everything yourself. Unlike elm-pages or elm-spa, it’s not a framework of any sort. If you want to bring in single-page application features, or other functionalities, you will have to build those in yourself. That said, it’s perfect for getting started with a basic environment.
As of this writing it includes:
- Hot Module Reload of all code in the app (including Elm)
- Tooling installation via
- Includes Elm,
- Includes Elm,
- Basic unit test examples
- Github Actions CI for running tests
- Recommends the Elm VS Code extension
If Vite is something you enjoy working with, I hope you’ll check it out! There is also a link in the README to set up a workspace using Gitpod if you want to try things out in a sandbox environment first.
I hope that helps you get started building an Elm application! Elm is an amazing language to learn and work with, and the tooling that exists to support it today makes working with it as delightful an experience as the language itself provides. Above all, I hope you enjoy learning and working with Elm in 2022!
If you’re new to Elm, and would like to learn more about it, check out the official Elm Guide.