lydell/elm-watch

Support packages (was: Input file globs)

hojberg opened this issue · 5 comments

Loving this project!!

It would be really neat if it was possible to provide a folder or glob to the input array.

Context: I'm working on some library code that don't have an entry file, and listing modules out manually is a bit of a pain.

Hi! Can you show me a concrete example of:

  • What your current, painful setup looks like. Both elm-watch.json as well as the input Elm files are interesting. A full GitHub repo for the complete context would be amazing if possible!
  • How you envision it could look like with globs.

I can in fact provide a full repository: https://github.com/unisonweb/ui-core

This is consumed as a "library" via elm-git-install.

Here's the elm-watch.json: https://github.com/unisonweb/ui-core/blob/main/elm-watch.json

A glob solution might look like this:

{
  "targets": {
    "UI": {
      "inputs": [
        "src/UI/**/*.elm"
      ],
      "output": "build/ui.js"
    },
    "Code": {
      "inputs": [
        "src/Code/**/*.elm"
      ],
      "output": "build/code.js"
    },
    "Lib": {
      "inputs": [
        "src/Lib/**/*.elm"
      ],
      "output": "build/lib.js"
    }
  }
}

Awesome, thank you!

So you have "type": "package" in your elm.json. As mentioned in at the end of What elm-watch is not, packages aren’t really supported by elm-watch – only applications are. (I even explored giving an error if elm.json has "type": "package" at one point, but it’s a long story.)

The thing here is that I don’t write many packages myself – only applications. And when I’ve written packages, they haven’t been very large. Either so small that running type checking in my editor (with an occasional elm make without arguments on the command line) has been enough. Or slightly larger, but then elm-test --watch has been great: Fast enough and I get to know that my package compiles, as well as the tests, and also that the tests pass.

I do have thought a lot about if elm-watch could be used for packages as well, and for a while I even supported "output": "/dev/null" in elm-watch.json for that purpose (type checking only). However, I’m not sure even that makes sense – it feels like watching packages is a similar but different thing:

  • It doesn’t make sense to have any output, ever. (In your project, build/*.js files are still created but are never used.)
  • It doesn’t make sense to specify inputs. All you need is elm make (without arguments) to be run when files change.
  • The watcher should read "exposed-modules" in elm.json to figure out which entry points there are for the package, and follow imports from there to know which files do and don’t affect compilation.
  • One might also want to mix watching the package itself, with watching a demo application, in the same elm-watch.json.

So, I don’t know, maybe this it how it should be:

{
    "targets": {
        "MyPackage": {
            "type": "package",
            "elm.json": "elm.json"
        },
        "Cool demo": {
            "type": "application",
            "inputs": ["demo/src/Main.elm"],
            "output": "build/demo.js"
        }
    }
}

In summary, I have a lot of thoughts around this, but I can’t make up my mind if it makes sense to build something like this or not. One thing that has been great while developing elm-watch is that I knew exactly what I needed: I had worked with Elm professionally for several years, and I knew the pain points and wishes I had from the old Elm setup at work. So I have built it exactly for my own use cases (while still keeping it general enough to be usable by others). Since I’m not a big package developer, packages was down prioritized, partly to avoid scope creep and partly since I don’t know exactly what’s needed for the package use case.

While the above JSON with "type" on each "target" might be the right way to do it (not sure), I’m reluctant to adding glob support to "inputs" as an “easier” solution. That would require another dependency (because I’m not going to implement globs by hand), and I’m very careful with dependencies in elm-watch. Also, everything in elm-watch is designed to not be Node.js specific because I have a dream of writing elm-watch in another language one day that can compile to a standalone binary. So I would have to come up with how to “standardize” which globs are supported etc. And I’m not sure it makes sense to use globs for a real application use case.

Finally: What we do at work is actually generating the elm-watch.json file (but for a different reason). Our startup script runs something like node generate-elm-watch-json.js && elm-watch hot. I guess you could do something similar.

What happens now?

  1. You can generate elm-watch.json and call it a day, probably. You’ll use elm-watch in a non-intended way, but it’ll probably work out and be useful for you.
  2. You could also try to make your tests cover all parts of the library and use elm-test --watch instead.
  3. Or you could make the demo application cover all parts of the library and use elm-watch for that, type checking the whole library as a side effect.
  4. There’s also https://github.com/Janiczek/elmid which might be interesting.
  5. Either way, I’ll leave this issue open to see if others pop up with the "type": "package" use case as well. I suspect it’ll take a while for anything to happen though (even if this turns out to be a popular request), because (at least currently) I don’t need this myself and I’d like to spend my time on https://github.com/lydell/elm-safe-virtual-dom. I’m mostly interested in tweaks and bug fixes of elm-watch for the moment – I like the very stable place it’s in right now.

@lydell thank you for this very thoughtful reply.

I think the package option sounds really cool. For now I'll follow your suggestion of generating the file. Thank you!