本ブログは移転しました。新しいブログは こちら です。

Elmでブログを作ったはなし

Overview

お正月くらいから、ちょこちょことElmを触り初めていたのですが、どうせならなにか作ってみたいと思いブログ(今この記事が載っているブログです)を作りました。その時に困ったことをメモがてら書いておきます。

※なお、このブログはサーバサイドをKotlin(SpringBoot)、クライアントサイドをElmで書いています。

※2020/1/1追記

ブログをHugoを使ったものに移行しました。 Elmで書いたブログはこちらになります。

環境ごとに設定を変えられるようにする

普通にReactやVueとかでクライアントサイドのコードを書くとき、例えばREST APIのURLとかは環境変数で設定することが多いと思います(たぶん)。

Elmでも同様のことがやりたかったのですが、直接Elmから環境変数的なものを読み込むことはできなさそうだったので、JavaScriptからflagsとしてElmのinit関数へ渡してやる方法を採用しました。

こんな感じです。

const app = Elm.Main.init({
  node: document.getElementById('main'),
  flags: {
    hostName: process.env.BLOG_HOST_NAME
  }
});

flagsについては公式ガイドで多くの人が採用している方法として紹介されていたように、JavaScriptのオブジェクト形式で渡し、Elm側でDecodeする方法を採用しました。

HttpでJsonを処理するときと同じようにDecoderを作ってあげてdecodeしてあげればOKです。 あとは、decodeした値をmodelに突っ込んで使う感じにしています。

type alias Config =
    { hostName : String
    }

flagsDecorder : Decode.Decoder Config
flagsDecorder =
    Decode.map Config
        (Decode.field "hostName" Decode.string)

decodeFlags : Decode.Value -> Result Decode.Error Config
decodeFlags flags =
    Decode.decodeValue flagsDecorder flags

init : Decode.Value -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
init flags url key =
    let
        decodedConfig =
            case decodeFlags flags of
                Ok config ->
                    config

                Err _ ->
                    Config ""
    in
    -- なんらかのinit処理

ブログ用のwidgetを描画する

ブログを作るにあたって、TweetボタンやHatenaブックマークへ追加するwidget(この記事の右下にあるやつですね)を採用したかったのですが、ElmのView内でscriptタグを生成することがver 0.19で出来なくなったとのことで、少しハマりました。

結果として、portsを使用して、JavaScriptでscriptタグを追加する方法を採用しました。

javascript側ではこんな感じでportの処理を受けています。

app.ports.addWidgets.subscribe(function() {
  requestAnimationFrame(function() {
      // ここでscriptタグを追加
  });
});

こちらの記事で紹介されているように、DOMが更新されたあとに処理を実行するためrequestAnimationFrame内でscriptタグを追加している点がポイントです。

まだ導入していないんですが、Google Analyticsのタグとかも同じような感じでいれれるかなーと思ってます。 まだ未調査なので、こちらも別のやり方で導入する必要がありそうなら記事を書くと思います。

Contents