Start with Elm

by Roman Zolotarev

This guide is all you need to start from zero to your first Elm app.

First of all, what is Elm? It is a purely functional compile-to-JavaScript language with great performance and no runtime exceptions. Designed by Evan Czaplicki in 2012.

Hello, World!

Let me start with the simplest app.

1
2
3
4
import Html

main =
  Html.text "Hello, World!"

This code compiles to JavaScript like this:

1
2
3
<!DOCTYPE HTML>
<script>/* Elm runtime */</script>
<script>Elm.Main.fullscreen();</script>

There are just two <script> tags: one with the app related code baked into 152KB of Elm runtime (to be fair, it can be minified and gzipped to 17KB) and another with Elm.Main.fullscreen() function call. This call puts "Hello, World!" to the DOM.

Voilà!

Now you are ready to install everything on your computer and try it by yourself.

Install

Tested with Node.js v6.9 and npm 3.10 on macOS Sierra 10.12. With different versions of Node.js or operating systems, your mileage may vary.

One of the benefits of Elm is its lean tooling. If you have Node.js installed, you can install Elm Platform with just two commands. Run these in your project directory.

# Initialize a project
npm init --yes

# Install Elm as dependency
npm install elm --save

Installing Elm Platform locally for every project takes about 50MB of disk space, but if you are working with multiple projects or with other developers, avoid installing Elm globally.

Make

To run your Elm app in a browser you need to compile it to JavaScript.

# Create an app
printf 'import Html\nmain = Html.text "Hello, World!"' > Main.elm

# Compile the app
$(npm bin)/elm-make Main.elm --yes

By default, elm-make generates index.html. Open it your browser. You should see Hello, World! text on the page.

Live reload

Every time you change *.elm files, you need to compile them and reload web page in the browser. To automate this part we can use elm-live. It is a helpful dev server.

# Install the server as dev dependency
npm install elm-live --save-dev

# Run the server
$(npm bin)/elm-live --path-to-elm-make="$(npm bin)/elm-make" Main.elm --yes

Add start script to your package.json:

...
"scripts": {
  "start": "elm-live Main.elm --yes --open",
  "test": ...

Now you can run the server with:

npm start

It compiles Main.elm to index.html and opens http://localhost:8000 in your browser. Now on every update of *.elm files they compile and then your browser reloads the page automatically.

Files

As result, you will get three artifacts in your project’s directory.

Main.elm

1
2
3
4
5
6
7
8
import Html         -- makes functions of Html module
                    -- visible in this scope Html
                    -- is a core Elm library
                    -- to handle DOM

main =              -- runtime calls function `main`
  Html.text         -- and it returns an element
    "Hello, World!" -- with text

elm-package.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
    "version": "1.0.0",
    "summary": "Hello, World!",
    "repository": "https://github.com/romanzolotarev/elm-hello-world.git",
    "license": "BSD3",
    "source-directories": [
        "."
    ],
    "exposed-modules": [],
    "dependencies": {
        "elm-lang/core": "5.0.0 <= v < 6.0.0",
        "elm-lang/html": "2.0.0 <= v < 3.0.0"
    },
    "elm-version": "0.18.0 <= v < 0.19.0"
}

package.json

1
2
3
4
5
6
7
8
9
10
11
{
    "scripts": {
        "start": "elm-live Main.elm --yes --open"
    },
    "dependencies": {
        "elm": "^0.18.0"
    },
    "devDependencies": {
        "elm-live": "^2.6.0"
    }
}

The rest (index.html, elm-stuff/, node_modules/) can be added to .gitignore.


I hope you walked through all these steps smoothly. If you have any questions or need help ask me on Twitter or via email.

Subscribe to my newsletter, if you are interested in Elm.



Further reading

A random illustration