Introducing elm-watch: elm make in watch mode. Fast and reliable

elm-watch recompiles whenever your Elm files change and reloads the compiled JS in the browser.

Are you tired of webpack, Parcel or Vite being buggy, slow or just a bit “meh” in its Elm support? Do you miss colored Elm error messages? Are you annoyed by hot reloading that stops working?

Well, I am. We’re so proud of Elm’s amazing compilation speed and beautiful error messages, but the first thing we do is wrap it in a complicated JavaScript tool that slows things down and prints errors in all red. Support for other languages than JavaScript and TypeScript always feels a bit like an afterthought in such tools.

I wanted to go back to that pure elm make experience. First I tried simply running elm make in a simple off the shelf watcher tool. But I ran into some problems:

  • Handling many rapid changes.
  • Supporting multiple apps a nice and fast way.
  • I missed hot reloading. It’s so nice to have when styling!

So I made elm-watch. It tries to be as simple, fast and reliable as possible. It also tries to reimagine the level of quality of hot reloading.

Note that elm-watch isn’t a replacement for webpack, Parcel or Vite. Like plain elm make, the job of elm-watch is to take .elm files and turn them into .js files. The rest is up to you. You can run webpack on the side for other frontend needs, but let elm-watch take care of Elm compilation. Personally, I use esbuild together with elm-watch (because it’s fast and simple). Example.

elm-watch started forming in my head early 2021. In May that year I started coding, and in March 2022 I released the first beta version. Since then I’ve released another dozen or so beta versions and started using it in production. Now it’s finally out of beta and I’ve released version 1.0.0!

The project now feels really solid and does everything I need. I do have some ideas for the future though.

Get started today!

npm install elm-watch
npx elm-watch init
npx elm-watch hot

The elm-watch repo readme contains everything you need to know:

Finally, a big thank you to Ed Kelly for testing and reporting issues! :raised_hands:

I also made a little video showing how to get started and a little bit of what it’s like using elm-watch. (Excuse my poor video making skills! It’s all a single take :blush: )

Update: Don’t miss the Elm Radio episode about elm-watch!

39 Likes

Thanks for this, it looks like a really slick piece of software!

Do you think that preprocessing could be a good fit for a new feature? I’ve been considering using the C preprocessor so that I can access __FILE__ and __LINE__ information, but this being incompatible with a watcher has been a blocker for me.

Interesting idea! However, there won’t be any preprocessing in elm-watch (unless it’s added to Elm itself).

  • Editors, elm-review and elm-test still need to understand the source code.
  • It would be slower. elm-watch does not read every single Elm file you have* – it just invokes the Elm compiler which does all the heavy lifting.
  • I have never felt the need for it myself.

* Well, it reads the top of each Elm file in parallel with running elm make to figure which files import which. I’ve spent a lot of time optimizing that. It’s now fast for a Node.js program – and fast enough for the use case – but running a preprocessor over all files would probably require writing it in another – faster – language. It would have to run before elm make so it has to be really, really fast.

One final thought: Since the postprocessing (of the JS output) that does exist in elm-watch simply calls a command of choice that you can configure, couldn’t preprocessing do something similar? I don’t think so, because the preprocessing command would basically have to copy the entire source code to a temporary location – with preprocessing directives replaced – and then elm-watch/elm would compile that. Elm reads files off the file system, and we can’t overwrite the source code.

Thanks for the reply, and your conclusion makes sense.

A couple of thoughts:

  • I don’t think it would need to be much slower. It would only need to re-pre-process files that have changed, and the elm compiler already needs to read changed files.
  • I agree that this would essentially require copying the sources to a temporary location. That’s the route I’m contemplating exploring in the future.

I recently started a new elm toy project and was missing something like this tool a lot! I already tried it out and it feels great!

Two things as feedback:

  • I feel like you could be more ambitious about the project name. In a way it’s an “enhanced” elm make and you could show that in the name!
  • I was confused why elm-watch hot does not take a debug-flag. When trying it anyways i got a great error message that told me to change that flag in my browser directly. Maybe you could state that in the help message already? That’s where i looked first. Not sure what other people think of if it’s just me :smiley:

Thanks again for the great tool, i really love it already after a single day of using it. It’s perfect to get a great dev-experience in a simple project and before that i was struggling with webpack and similar tools that just were too fancy for my simple use case. Thanks :heart: !

Thank you!

  • I like the simplicity of the name elm-watch. “Want a watcher for Elm? Use elm-watch!”
  • Ah, I’ve never thought of that before! Seeing elm-watch make [--debug|--optimize] [targets...] and elm-watch hot [targets...] right after each other, one might wonder why only one of them takes flags, yes! It probably makes sense to mention that in the help message as you say. Good feedback!

@IloSophiep I made a PR to tweak the help text: Tweak --help text by lydell · Pull Request #24 · lydell/elm-watch · GitHub. Would you mind checking it out, and see if the new text is more clear?

1 Like

When I first got into Elm this spring, I was surprised to find the Elm CLI didn’t include a --watch mode that does exactly this. A little googling lead me to elm-watch. Once your project gets past where you can do all of your of browser based iterating via reactor, adding elm-watch is a no brainer.

@lydell Very nice work, happy to see this officially out of beta. Gotta find an excuse to try that esbuild setup.

2 Likes

In case it’s useful to anyone else, there’s a general tool that works arbitrary commands: entr. Here’s a post that gives some examples on using it as well: entr: rerun your build when files change

2 Likes

I’ve bumped into entr before – it looks really cool! I haven’t tried entr though, but I have tried other “generic watcher tools”. These are the problems I ran into: GitHub - lydell/elm-watch: `elm make` in watch mode. Fast and reliable.

2 Likes

This is perfect for the new project I’m starting. I was planning on using elm make instead of parcel on it to get to know my build process better and this will fit in nicely!

Thank you for the hard work.

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.