The Elm ecosystem is one of the friendliest I’ve used (from the incredible compiler messages to the friendly folks on Elm Discourse and Slack). It’s mature enough now, though, that there are a variety of dev tools that are widely used but not part of the official documentation.

Since I find myself repeating build instructions on GitHub projects, here’s an attempto DRY it up (at least for now).

Standard Build

All Elm projects can be built with elm make, such as:

elm make examples/Main.elm --optimize --output=elm.js

… which builds the example specified in examples/Main.elm and compiles it to elm.js.

Note that all build tools use the elm.json configuration file, and any code not in src needs to explicitly added under source-directories in the file. So, in this case:

"source-directories": [
        "src",
        "examples"
    ],

Optimized Build

There are a variety of tools that can be included in a build piepeline, including tests, formatting, and further optimization, and minification of the generated JavaScript.

I typically use the following packages, which can be installed with npm (globally so they work for all Elm projects, or omit the -g flag to install locally) like so:

npm install -g elm-coverage
npm install -g elm-format
npm install -g elm-test
npm install -g elm-optimize-level-2
npm install -g elm-minify

Note that elm-minify is deprecated, though it works fine for now as a wrapper for terser. For an alternative minification, see the terser command recommended by elm-optimize-level-2. There are other optimization tools out there, for those inclined to do some research.

Using the above tools, the full build looks like the following, which can be run as a shell script:

elm-format src/ --yes

# elm-coverage .
elm-test

elm-optimize-level-2 src/Main.elm --output=elm.js

elm-minify elm.js
gzip --keep --force elm.min.js

elm-coverage is commented out because there some compabitility issues at the time of this writing; when it works, there is no need to run elm-test separately.

The resulting minified file elm.min.js.gz is the one that should be used in production.

Elm Live

Note that there’s no need to run the build process while developing, as Elm has good live reload tools. I use elm-live:

npm install -g elm-live

To use it to compile src/Main.elm and use it with main.html:

elm-live src/Main.elm ---optimize -open --start-page=main.html -- --output=elm.js

… where main.html can be something minimal like so:

!DOCTYPE html>
<html>
  <head>
    <title>Elm App</title>
    <script src="elm.js"></script>
    <style>
    </style>
  </head>
  <body>
    <div id="elm"></div>
    <script>
    var app = Elm.Main.init(
          { node: document.getElementById("elm"),
            flags: {
                windowWidth: window.innerWidth,
                windowHeight: window.innerHeight
            }
          }
    );
    </script>
  </body>
</html>

The flags are not necessary to provide, but it’s open nice to have the window width and height for use in the Elm app. Note that elm.js should be replaced with the minified / compressed file, if using one, like elm.min.js.gz in production.