The only thing that is slower than touching the DOM is talking to servers. Especially for folks on mobile phones with slow internet. So you can optimize your code all day with
Html.Keyed, but your application will still feel slow if it loads slowly!
A great way to improve is to send fewer bits. For example, if a 122kb asset can become a 9kb asset, it will load faster! We get results like that by using the following techniques:
- Compilation. The Elm compiler can perform optimizations like dead code elimination and record field renaming. So it can cut unused code and shorten record field names like
userStatusin the generated code.
ifstatements to ternary operators. They turn
'A'. Anything to save a few bits!
- Compression. Once you have gotten the code as small as possible, you can use a compression algorithm like gzip to shrink it even further. It does particularly well with keywords like
returnthat you just cannot get rid of in the code itself.
Elm makes it pretty easy to get all this set up for your project. No need for some complex build system. It is just two terminal commands!
Step one is to compile with the
--optimize flag. This does things like shortening record field names.
uglifyjs, but you can use a different one if you want. The neat thing about
uglifyjs is all its special flags. These flags unlock optimizations that are unreliable in normal JS code, but thanks to the design of Elm, they are totally safe for us!
Putting those together, we can optimize
src/Main.elm with two terminal commands:
elm make src/Main.elm --optimize --output=elm.js uglifyjs elm.js --compress 'pure_funcs=[F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9],pure_getters,keep_fargs=false,unsafe_comps,unsafe' | uglifyjs --mangle --output elm.min.js
After this you will have an
elm.js and a smaller
uglifyjsis called twice there. First to
--compressand second to
--mangle. This is necessary! Otherwise
uglifyjswill ignore our
Note 2: If the
uglifyjscommand is not available in your terminal, you can run the command
npm install uglify-js --globalto download it. If you do not have
npmeither, you can get it with nodejs.
It is hard to remember all those flags for
uglifyjs, so it is probably better to write a script that does this.
Say we want a bash script that produces
elm.min.js files. On Mac or Linux, we can define
optimize.sh like this:
set -e js="elm.js" min="elm.min.js" elm make --optimize --output=$js "$@" uglifyjs $js --compress 'pure_funcs=[F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9],pure_getters,keep_fargs=false,unsafe_comps,unsafe' | uglifyjs --mangle --output $min echo "Compiled size:$(wc $js -c) bytes ($js)" echo "Minified size:$(wc $min -c) bytes ($min)" echo "Gzipped size: $(gzip $min -c | wc -c) bytes"
Now if I run
./optimize.sh src/Main.elm on my TodoMVC code, I see something like this in the terminal:
Compiled size: 122297 bytes (elm.js) Minified size: 24123 bytes (elm.min.js) Gzipped size: 9148 bytes
Pretty neat! We only need to send about 9kb to get this program to people!
The important commands here are
uglifyjs which work on any platform, so it should not be too tough to do something similar on Windows.
I recommend writing a
Note: In theory, it is possible to get even smaller assets with Elm. It is not possible right now, but if you are working on 50k lines of Elm or more, we would like to learn about your situation as part of a user study. More details here!