Elm Development Environment
First off, my apologies for the deep silence of late. I’m pretty deep in the trenches when my Master’s semesters are running and I simply had to take a personal break during my summer. I’m hoping this post can help me pick up my cadence again!
I recently dove back into Elm development, only to find that the community has evolved rapidly between versions 0.16 and 0.18 (current as of this writing). I thought I’d share my notes on how I have my new development environment set up, now that we have more options beyond simple text editors (or vim).
Right now, my basic environment looks like this:
- Running on OS X Sierra
- Elm 0.18
- Visual Studio Code
- Sascha Brink’s Elm Language Support extension for VS Code
That’s all I’m using to get a nice rapid development environment up and running.
Project Structure
I’m currently structuring my projects like this:
project_dir/ |-- elm_stuff/ |-- src/ | |-- Main.elm | |-- Module1.elm | |-- Module2.elm | \-- ... |-- static/ | |-- styles.css | |-- whatever.js | \-- ... |-- elm-package.json |-- elm.js |-- index.html |-- reactor_debug_index.html \-- reactor_compiled_index.html
Let’s break it down!
elm_stuff/
is just the auto-generated stuff built by Elm.
I’ve defined my elm-package.json
to keep all my .elm
source files under the src/
directory, like so:
{ ... "source-directories": ["src"], ... }
I drop all of my non-Elm static files (stylesheets, JavaScript, whatever) into the static/
directory.
elm.js
is the compiled app generated by elm-make, as usual.
index.html
is my actual production index page. This will likely be custom to you.
Now, for those two funny reactor_ pages.
Getting VS Code to play nice with elm-reactor and elm-make
elm-reactor gives us nice instant refresh behavior for code changes. VS Code gives us a nice editor and auto-save behavior. Getting the two to play nicely together (and elm-make) isn’t too difficult, but does take a couple tricks. Further, debug (with elm-reactor) vs production (with elm-make) require different tricks to get them to work.
For debugging (using elm-reactor), I started with this recommendation by Denis Kolodin and made some modifications. This one can reference your entry point .elm
module file directly and elm-reactor will do the rest. I did a tiny bit of cleanup and am currently using the definition from this gist.
For development debugging from there, my development process looks like this:
- Starting up: Cmd+Shift+P (on Mac), type
Elm: Reactor Start
, then open the link in your browser (this will be clickable from your VS Code console output). - Iterative development: Make your edits, refresh the browser page!
- Shutting down: Type
Elm: Reactor Stop
before exiting VS Code. (Check the Troubleshooting section below about stopping elm-reactor!)
[Update: There’s some talk about ports
not working with the debug version, but this no longer appears to be a problem with Elm 0.18. Just capture the app created at startup: var app = runElmProgram();
]
For testing the compiled version (using elm-make), I started with this recommendation by Denis Kolodin. This one needs to reference your compiled elm.js
, but there’s a catch from VS Code: You must run elm-make with the entry point .elm
module as the active window! If you don’t do this, it will compile a different module and you’ll get Elm startup errors. I ran into this problem multiple times, each time wondering why nothing was showing up until I checked the JS console output for errors. To help streamline this (and prevent confusion), I modified the HTML to spit out a visible error message if my Main module isn’t defined – I’m currently using the implementation from this gist.
From production debugging from there, my development process looks like this:
- Starting up: Cmd+Shift+P (on Mac), type
Elm: Reactor Start
, then open the link in your browser (this will be clickable from your VS Code console output). - Iterative development: Make edits, make
Main.elm
the active window (check the Troubleshooting section below), typeElm: Make
, refresh the browser page. - Shutting down: Type
Elm: Reactor Stop
before exiting VS Code. (Check the Troubleshooting section below about stopping elm-reactor!)
That’s all I needed to get up and running in a fast, iterative way with VS Code, elm-reactor, and elm-make, plus pulling in external styling.
Troubleshooting
I’ve run into a few gotchas with this:
- Tip: Always make sure you stop an elm-reactor process before exiting VS Code.
- If I start elm-reactor from VS Code, but close VS Code without stopping elm-reactor, it will create a dangling process. I’m unable to start another elm-reactor from the command line or VS Code, or stop the current process. I have to kill the process manually.
- Tip: Always have your
Main.elm
as the active window in VS Code when you elm-make.- Running elm-make will generate
elm.js
based on whatever the currently active window module is. If you compile from a different module, it’s likely to break yourreactor_compiled_index.html
(which is the reason for the extra error message conditional – I found this to be more obvious then investigating the JS console).
- Running elm-make will generate
- Tip: elm-reactor has some pre-defined path references you can access from your HTML.
- Prefixing
/_compile/
will point to the root of your project directory. - Prefixing
/_reactor/
will give you access to things in the reactor space, such as the fancywaiting.gif
. - Referencing
/elm.js
seems to work the same as/_compile/elm.js
, so I’m guessing elm-reactor copies theelm.js
file into its root directory – but other references, like for/_compile/static/styles.css
, don’t appear to work that way. This may be behavior special toelm.js
.
- Prefixing