The question of code-splitting in Elm comes up fairly routinely.
The apparent low-hanging-fruit of code-splitting with Elm's pure/immutable philosophy has led me to explore this a few times with my compiler work on Lamdera.
Here are some of the challenges I've found:
It's a little trickier than it looks because Elm's DCE is actually not DCE (dead code elimination) at all, it's LCI (live code inclusion).
At the JS output stage, the compiler recursively pulls in defs and subdefs for only the things that are actually part of the project as it writes out everything used by main
down.
While crying "this is not DCE" might seem a little pedantic, it has a practical impact on code-splitting for which saying "DCE" wouldn't make any sense, so I'll call it "LCI" for the purpose of explaining further.
Elm's LCI has two practical impacts:
The symbol obfuscation algorithm, which replaces things unnecessary for runtime, like myCustomRecordFieldName
or myMeaningfulFunctionName
with something like r
or aP
(starting at a
and going upwards to ZZZ
), happens alongside the live-code-including output process.
This means you could reposition one function call in your project source, re-compile, and end up with a completely different obfuscation set in Javascript.
Because functions can depend on other functions, knowing the obfuscated name of those functions, especially the commonly re-used ones from core, is important – otherwise, how do you know what to call?
Thus, due to the prior point, if you have a code-split segment, you now can't re-use that with any other project without also retaining some knowledge of what the symbol obfuscation mapping was. Any sub-segments cannot do so either, all the way down.
So each code split segment would have a unique "fingerprint" of obfuscation making it's "just re-use it" utility problematic.
Perhaps with some effort these problems could be overcome (I've been thinking about whether it's possible to have some sort of more stable obfuscation algorithm), but this is what prevents code-splitting being low-hanging fruit as things stand today, AFAIK!