Edited at
ElmDay 2

Elm 0.19 の初期化方法 6 種類

2019 年 Elm をはじめる人が次に読むページです。

(いえ、どこから読んでも良いです)

この記事では Elm 0.19 のプログラム初期化の方法を紹介します。

(Elm コードの書き方は紹介しません)


出力は HTML と JS の2種類

HTML を出力(デフォルトは index.html)。

elm make src/Main.elm

ただしこの方法では CSS ファイルへのリンクやメタ情報を埋め込むことができないので、大抵は次のようにして JS を吐き出して HTML から呼び出します。

elm make src/Main.elm --output=elm.js

<!DOCTYPE html>

<html>
<head>
<script src="elm.js"></script>
<title>Elm App</title>
</head>
<body>
<script>
Elm.Main.init();
</script>
</body>
</html>

Node.js 環境ではこんな感じ。

const { Elm } = require("./elm.js");


静的な HTML

main に直接 HTML を書きなぐれます。

module Main exposing(main)

main : Html msg
main = a [ href "https://elm-lang.org/" ] [ text "Elm" ]

Elm.Main.init({ node: document.getElementById("elm-node") });


Browser.*

Elm 0.19 では main を Browser モジュールを使って書きます。0.18 以前では Html.program とか書いてありますが捨ててください。

詳しくは公式ガイドとパッケージのドキュメントを見てください。


Browser.sandbox

HTTP などを使わない簡単なプログラムを作ります。

sandbox :

{ init : model
, view : model -> Html msg
, update : msg -> model -> model
}
-> Program () model msg

HTML から呼び出す場合にはノードに埋め込んで使います。

Elm.Main.init({

node: document.getElementById("elm-node")
});


Browser.element

HTTP など副作用のある処理がある(ほとんど)場合はこちらを使います。

element :

{ init : flags -> ( model, Cmd msg )
, view : model -> Html msg
, update : msg -> model -> ( model, Cmd msg )
, subscriptions : model -> Sub msg
}
-> Program flags model msg

HTML から呼び出す場合にはノードに埋め込んで使います。

Elm.Main.init({

node: document.getElementById("elm-node")
});

Flags や Ports の機能を使うと Elm <=> JS 間でデータのやりとりができます

var app = Elm.Main.init({

node: document.getElementById("elm-node"),
// フラグを渡す
flags: { initializedAt : Date.now() },
});
// Elm から値を受け取る
app.ports.ping.subscribe(function (text) {
// Elm に値を返す
app.ports.pong.send(text);
});


Browser.document

element とほとんど同じですがタイトルを動的に切り替えることができます。

document :

{ init : flags -> ( model, Cmd msg )
, view : model -> Document msg
, update : msg -> model -> ( model, Cmd msg )
, subscriptions : model -> Sub msg
}
-> Program flags model msg

type alias Document msg =
{ title : String
, body : List (Html msg)
}

HTML から呼び出す場合は画面いっぱいに表示します。埋め込みはできません

Elm.Main.init();

Flags と Port はもちろん使えます。


Browser.application

最終進化形です。 組み込みの SPA ルーティング機能が使えます

application :

{ init : flags -> Url -> Key -> ( model, Cmd msg )
, view : model -> Document msg
, update : msg -> model -> ( model, Cmd msg )
, subscriptions : model -> Sub msg
, onUrlRequest : UrlRequest -> msg
, onUrlChange : Url -> msg
}
-> Program flags model msg

HTML から呼び出す場合は画面いっぱいに表示します。埋め込みはできません

Elm.Main.init();

Flags と Port はもちろん使えます。

注意点としては、埋め込み(element)+組み込みの SPA ルーティング機能を使うことはできません。理由と対策についてはこちらを見てください。


Platform.worker

画面なしのプログラムです。Node.js での使用が想定されています。

worker :

{ init : flags -> ( model, Cmd msg )
, update : msg -> model -> ( model, Cmd msg )
, subscriptions : model -> Sub msg
}
-> Program flags model msg

const { Elm } = require("./elm.js");

const app = Elm.Main.init({
flags: { initializedAt : Date.now() },
});
app.ports.pong.subscribe(function (text) {
console.log(text);
});
app.ports.ping.send(text);

worker は elm-test などで使われています。

(追記)Node.js で使えるとはいえ、実用できるのはせいぜい小さなツール程度です。プロダクションのサーバーサイドなどガチ用途で使うのは絶対にやめてくださいね!


まとめ

Elm でどんな初期化ができるのかをざっと紹介しました。

もりもりアプリを作っていきましょう。