Separating the Elm runtime from application code

680 views
Skip to first unread message

Murphy Randle

unread,
Jan 20, 2016, 9:08:00 AM1/20/16
to Elm Discuss
I've been experimenting with mounting Elm applications into an existing React application (this is my vector to get us using Elm at work). Using webpack, I can import a 'Main' Elm module into a JS file, and have access to the Elm object, in order to mount an Elm app at some part of the DOM.

This is great! It's simple to understand, and simple to set up. The problem is that for each little Elm app (or component) that's imported into a JS file, the Elm runtime is copied. That adds about 100kb to my bundle for each Elm component I add!

In order to get around this and only include the Elm runtime once, I created one single `Main.elm` file that imports all of my other Elm components (each of which has a `main` function defined within for rendering). Then, wherever I want to mount one of my small Elm components (let's call it Foo), I require that main file, then I mount that specific module to the page: `elm.embed("Main.Foo", <element>)`.

This works, but it's not very intuitive, and convolutes the nice filesystem layout we had before.

Also, the ports for all little Elm components must be created in that single Main file, instead of in the Main file for each component that we had before.

Lastly, in order for any tasks to be run, the 'Main' module must be mounted somewhere on the page (some invisible div).

I don't expect that there's a reliable way to separate the elm runtime code from the application code without modifying the compiler. Does anyone else have a better workaround? Would a change like this to the compiler be non-trivial?

Alexey Shamrin

unread,
Jan 20, 2016, 4:36:06 PM1/20/16
to Elm Discuss
Hi Murphy,

You can build several Elm main modules into one JavaScript file by simply passing them all to elm-make:

elm-make First.elm Second.elm --output bundle.js

Here's First.elm:

module First where
import Html exposing (span, text)
main
= span [ ] [text "Hello First!"]

And Second.elm:

module Second where
import Html exposing (span, text)
main
= span [ ] [text "Hello Second!"]

You would then embed them as follows:

var first = document.getElementById('first');
Elm.embed(Elm.First, first);
var second = document.getElementById('second');
Elm.embed(Elm.Second, second);

You can find the complete example at  https://gist.github.com/shamrin/06599db083cf98e7eef2

Alexey

среда, 20 января 2016 г., 17:08:00 UTC+3 пользователь Murphy Randle написал:

Murphy Randle

unread,
Jan 20, 2016, 6:29:43 PM1/20/16
to Elm Discuss
Thanks, Alexey! I'll try that out as soon as I get the chance.
Reply all
Reply to author
Forward
0 new messages