Elm reactor - init with flags for 0.19

Hi,

I want to be able to develop my SPA in elm using reactor and pointing to a dev web api. Previously what I did was have a separate elm module and pass the server url parameter in the flag - as per the discussion below:

The nice thing about doing it this way is that I could port the compiled js code to the application server without having to make any code changes to my elm files.

This does not seem to work anymore in elm 0.19 with the Browser.element . I understand that the api has changed and I can’t figure out how to pass the defaultflag to the init function - I get an error similar to the one below:

Any help is greatly appreciated. Thanks.

The 1st argument to element is not what I expect:

39| Browser.element
40|> { init = init defaultFlags
41|> , update = update
42|> , subscriptions = subscriptions
43|> , view = view
44|> }

This argument is a record of type:

{ init : ( Model, Cmd Msg )
, subscriptions : Model -> Sub Msg
, update : Msg -> Model -> ( Model, Cmd Msg )
, view : Model -> Html Msg
}

But element needs the 1st argument to be:

{ init : flags -> ( Model, Cmd Msg )
, subscriptions : Model -> Sub Msg
, update : Msg -> Model -> ( Model, Cmd Msg )
, view : Model -> Html Msg
}
1 Like

If you do not care about compiling your own compiler:

We forked the compiler to be able to do this: https://github.com/CurrySoftware/compiler

Now you can use <script src="/src/Main.elm?output=js" charset="utf-8"></script> to get the JavaScript from the reactor and from there on the solution is identical to the one you linked.

Thanks a lot. Will have a look - but was hoping for something simpler :slight_smile:

If you have Haskell platform installed, you can run/compile this script to simulate 0.18 /_compile/ feature.
If the compilation fails, you can detect it in the index.html and show the reactor errors in iframe.
Example: https://pastebin.com/t8VUNzyg

Folks, what features do you use in elm reactor that is not in elm-live?

I often use elm-live as it has some nice features like elm make flags support (particularly --output so you can use flags and --debug), push-state (a default file to serve that is handy for SPA routing tests), hot-reloading and interface/port binding configuration, and I am not missing elm-reactor, so I wonder…

2 Likes

Elm Live is very complete. But for my use case I needed to build my own script. If elm-live updated the output content with a variable in the top showing wether the compilation were successful or not, I would be able to use it.

For strictly elm based apps I’ve used elm-live in the past and was happy with it.

But for those which are a mixture of things I found elm-live likes overwriting my custom Index.html page (despite using the --output flag to only update the java-script). Maybe there’s a flag I’ve missed - but I couldn’t work it out.

The most important advantage of elm reactor over elm-live I found: elm reactor works without messing up the file index.html in the elm project directory.
Could not get elm live to work like that. When I used the --output option, it stopped working, sending index.html(or an error message if there is no index.html anymore) to the browser instead of the compilation output.
This problem was not enough to prevent use of elm-live in my projects so far.

That could be a bug with elm-live, I just want to confirm that you’re both running elm-live like this:

elm-live Main.elm -- --output=elm.js

If you leave out that first --, then the output flag gets passed to elm-live which might just ignore it. Flags after the -- are passed to elm make.

3 Likes

Ah right, it also happened to me at first to overwrite my index.html by using the wrong arguments, that’s why I usually put my index.html in a subdirectory to avoid messing with it inadvertently, for example using ./public/index.html:

$ elm-live src/Main.elm -d public -- --output=public/elm.js

elm-live will serve ./public/index.html that must include elm.js and init the elm application. You can also put some css or other static files in public/. If you forgot the -- --output, the generated index.html will be in . and won’t overwrite your carefully crafted one (which is indeed annoying).

2 Likes

Indeed I was leaving out the first -- which makes all of the difference.
Thanks Sidney!

Testing this, I have renamed the Elm entry file to Main.elm, and used this commandline:
elm-live Main.elm -- --output=elm.js
With this setup, elm-live responds with a 404 Not Found with a the following body:

File Not Found

I see that the elm.js file was created tough.


Based on the guide from @dmy at Elm reactor - init with flags for 0.19 - #10 by dmy, I found this working setup:
elm-live Main.elm -d outputtoignore -- --output=outputtoignore/index.html

I’m not sure though why you call it outputtoignore, so let me try to explain elm-live behavior in more details as far as I understand it.

AFAIK, when connecting to localhost:8000 (by default), elm-live will always serve index.html or 404 if not found.

If you specify a path in the url, it will serve the corresponding file or 404 if not found (unless you use --pushstate in which case it will always serve index.html).

For compilation, elm-live performs exactly like elm make:

1. Let “elm make” generate index.html

If you don’t need any additional javascript (like flags, ports, custom elements or observers), you can let elm make generate the html file:

$ elm-live src/Main.elm

This will basically call elm make src/Main.elm then start a web server in .. So index.html will be generated by elm make in . and init the elm application. elm-live will then serve this index.html.

2. Tell “elm make” to generate a js file and use your own index.html

If you need your own index.html file (to add some flags or some javascript), then use elm make --output to generate a javascript file without the html:

$ elm-live src/Main.elm -- --output=elm.js

Every option after the -- is passed to elm make. (you can call elm.js main.js instead or whatever name, given that you use it correctly in index.html).

It is then your responsibility to initialize elm in an index.html file that will be served. If you don’t have any index.html like in your first example, you will get a 404.

However as you noticed, if you put your own index.html in . and forgot the --output=elm.js, this will generate ./index.html and overwrite your own. But this is not elm-live that overwrites your index.html, this is elm make. You can test exactly the same behavior by using only elm make.

This is why I advise to put your own index.html in a subdirectory and use elm-live -d to serve files from it (again always index.html by default without a specific url).

I actually do it even when not using elm-live for the same reasons, you could use instead for example python3 -m http.server 8000 from this subdirectory. The difference is that elm-live also injects some additional javascript itself to support live reloading, and watches source files to recompile when needed.

As a bonus, all your static files (index.html, css, js, images) and the generated elm.js will be cleanly grouped in a subdirectory that you can serve directly when deploying on github pages or netlify for example (preferably after minification).

3 Likes

This is to communicate the meaning of this file to people:
When someone finds a file called index.html, how do they know that this is just a temporary artifact from a development tool and not meant to be read or maintained by humans? How do they know it should not be tracked in version control?
Moving it into a directory called outputtoignore is just a way to communicate this better.

Also, I usually avoid having temporary files or build artifacts being written to the root directory of a project. That is why, before I learned this way of setting up elm-live in this thread, elm-reactor had a big advantage in this regard.

In this case, I would just put it in .gitignore, but I think I get your point.

That is a good point :+1:
Reducing the number of entries in gitignore felt good :smiley:

Reducing the number of entries in gitignore

image

1 Like

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