アセットサイズの縮小
DOMを操作するよりも更に遅い処理があるとしたら、それはサーバからのデータの取得だけでしょう。遅いネットワーク回線にあるモバイル端末においては更に深刻です。Html.Lazy
やHtml.Keyed
による最適化が常に有効なのは確かですが、もし読み込みが遅いのならアプリケーションは遅いままだと感じられるはずです!
これを改善する良い方法は、送信するデータをもっと少なくすることです。たとえば、122キロバイトのアセット(サーバからブラウザに送られるファイル)を9キロバイトにすることができれば、読み込みはずっと早くなります! 次のような手法を使うことで、そのような結果を得ることができます。
- コンパイル。 Elmコンパイラは、デッドコード除去やレコードフィールドの名前変更のような、パフォーマンス最適化を実施することができます。つまり、生成されたコードの使われていないコードを取り除いたり、
userStatus
のようなレコードフィールド名を短くしたりすることができます。 - ミニファイ。 JavaScriptの世界には、いろいろな変換を行う『ミニファイア』(minifiers)と呼ばれるツールがあります。これは、変数名を短くしたり、インライン化をしたり、
if
文を3項演算子へと置き換えたり、'\u0041'
を'A'
に置き換えたりします。いずれもデータ量を削減するためです! - 圧縮。 デッドコード除去やミニファイによってコードを可能な限り小さくしたら、そのあとgzipのようなアルゴリズムを使うことでコードを更に圧縮することができます。それ自身を単純に取り除くことが難しい
function
やreturn
のような予約語に対して特に有効です。
Elmではこれらの最適化をプロジェクトに対してとても簡単に設定することができます。複雑なビルドシステムは必要ありません。たったふたつのターミナルコマンドだけでできるのです!
最適化のやりかた
最初のステップは、--optimize
フラグを付けてコンパイルすることです。これはレコードフィールドの名前を短くするようなことを行います。
次のステップは、出力されたJavaScriptコードをミニファイすることです。私はuglifyjs
というミニファイアを使っていますが、別のあなたが好きなものを使っても構いません。uglifyjs
のいいところは、その特別なフラグにあります。そのようなフラグを付けると、通常のJSコードに対して実施しても正しく動くかわからない高度な最適化が有効になりますが、Elmのデザインのお陰でこれらの最適化はまったく安全です!
これらを合わせると、src/Main.elm
を次のようなふたつのターミナルコマンドで最適化することができます。
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
コマンドの実行が完了すると、elm.js
とそれがもっと小さくなったelm.min.js
ファイルのふたつが生成されるでしょう!
Note 1:
uglifyjs
は、最初の--compress
とふたつめの--mangle
の2回呼び出されます。これは必要なことです! さもなければ、uglifyjs
はpure_funcs
フラグを無視してしまいます。Note 2: もし
uglifyjs
コマンドがターミナルで使えない場合は、npm install uglify-js --global
を実行してuglifyjs
をダウンロードしてください。もしnpm
もないようであれば、nodejsから入手してください。
スクリプト
あのようなuglifyjs
のフラグをみんな覚えるのは大変ですので、おそらくそれを実行するスクリプトを書いたほうがいいでしょう。
elm.js
とelm.min.js
ファイルを生成するbashスクリプトが欲しい場合もあると思います。MacかLinuxなら、optimize.sh
を次のように定義すればいいでしょう。
#!/bin/sh
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"
これで、もしTodoMVCのプロジェクト上で./optimize.sh src/Main.elm
を実行すれば、次のようなものがターミナルに出力されるのを見ることができるでしょう。
Compiled size: 122297 bytes (elm.js)
Minified size: 24123 bytes (elm.min.js)
Gzipped size: 9148 bytes
なかなかいいですね! このプログラムをユーザに渡すときは、たった9キロバイトほどを送るだけでいいのです!
このelm
とuglifyjs
はどのプラットフォームでも動く重要なコマンドですので、同じようなことをWindowsで行うのはとても大変というほどでもありません。
アドバイス
これまで見てきたように、Browser.application
を使い、単一のJavaScriptファイルへとコンパイルするのを書くのをお勧めします。そのJavaScriptファイルは、ユーザがページを最初に訪れたときにダウンロード(とキャッシュ)されるでしょう。JavaScriptを生成する他の有名なプログラミング言語と比較しても、Elmはずっと小さなファイルを作成しますので、ここで見ていただいたように、この戦略に従えばよりいっそう良い結果を得られるでしょう。
Note: 理論的には、Elmでこれよりもさらに小さなアセットにすることも可能です。これは現段階では不可能なのですが、もしあなたがElmで5万行以上のコードを書いているなら、ユーザの使用状況の調査のひとつとして、あなたの状況を教えていただけたらと思います。くわしくはこちらをご覧ください!