How to compile Elm files on save
When writing JavaScript I am used to have a tool like Webpack or Browserify that automatically compiles the code whenever I save my changes. Therefore one of the first things I wanted to do in Elm is to set up the same build process.
#Elm’s compiler has no watch option
Unfortunately Elm’s compiler does not support watching files right out of the
box. elm make
only compiles once when executed and does not have a --watch
option.
There is elm reactor
, that does watch for file changes and recompiles your
code, but it starts a server, which serves its own HTML file. This is fine for
small experiments or while learning the language. As soon as you want to add
custom CSS or integrate Elm into an existing code base you have to use something
else though.
#Why I don’t use webpack or grunt with Elm
I know that there is elm-webpack-loader and elm-grunt, but starting an Elm project with one of these big JS build tools pulls in a lot of code. In the end one reason I chose Elm is to worry less about JavaScript.
Since Elm has its own compiler that imports Elm packages and bundles your code into one file, webpack is too heavy just for file watching. When I write JavaScript I also avoid grunt/gulp. The more code is written to build your project, the more can go wrong and newcomers have to learn when they want to make changes to the build process.
This is why I try to keep it as simple as possible and mainly use npm’s
scripts
field in package.json
instead. It does not require pulling in
another dependency and is what I recommend for Elm as well.
#File watching with chokidar
The most popular JS build tools, e.g. webpack, browserify and gulp, use the same package to watch for file changes: chokidar. It deals with problems each operating system has when it comes to watching files and provides one interface that abstracts away all the workarounds needed to make it work across different environments.
Chokidar does not offer a CLI interface out of the box, but there is chokidar-cli, which wraps it and offers exactly what I need: executing a command on each file change.
This is what the command looks like:
chokidar <file pattern> -c <command>
#My Elm build setup
Whenever I start a new Elm project I can now set it up by adding
chokidar-cli and one line to
my package.json
:
-
Install Elm with:
npm install elm --save-dev
-
Install chokidar-cli with:
npm install chokidar-cli --save-dev
-
Open
package.json
and add the following line:
{
…
"scripts": {
"watch": "chokidar '**/*.elm' -c 'elm make Main.elm --output elm.compiled.js' --initial"
}
…
}
This line tells chokidar to watch for all files ending with .elm
in the root
and subfolders. It then runs elm make Main.elm --output elm-compiled.js
for
each change. If your Elm entry file is not called Main.elm
or your output
JavaScript file should be called differently change this line.
Now you can execute npm run watch
to get
Elm’s awesome compiler messages
when saving your changes and the updated compiled JavaScript after refreshing
the browser.