JSerがElmとFirebase使ってみた



JSerがElmとFirebase使ってみた:

業務ではABテストなどでVanilla JSばかり書いていた私がElmに興味を持ったのでElmとFirebaseを連携させたアプリを作成してみました。

Elmはバックエンド出身の人がフロントを書くために使うというパターンが多いような気がしていますが、私のようなフロントの人間がElmを使ってみたというのも参考になるかと思い投稿しました。

初めての投稿なのでお手柔らかにお願いします。


Elmとは

https://elm-lang.org/

haskellで書かれた関数型altJSです。haskellに似ている部分が多くあるものの結構な部分が削ぎ落とされており文法がシンプルなので自分のようなフロントエンド出身の人間でも扱いやすいと感じました。

(ver 0.19)


作成したアプリについて



g.gif


クリックするとランダムで背景色が変わるというものです。これではわかりづらいですがランダム値はFirebaseに保存されています。


主な目的

  • Elmに慣れること
  • ElmとFirebaseの連携


Elmを始める&ドキュメント

「2019年 Elmをはじめる人が最初に読むページ」
https://qiita.com/arowM/items/5ec5853298fc880353b7

まずはこれを読んで「公式ドキュメント(Elm Guide)」がいかに重要なのかを知っておきます。その上で以下の内容を読むことで知識を深めていきます。

<公式ドキュメント>
https://guide.elm-lang.org/

<公式ドキュメント:翻訳版>

英語が苦手なら有志の方々が翻訳している日本語版もある
https://guide.elm-lang.org/

※一部未翻訳部分もあるので、そういうところはGoogle翻訳とかで。

<基本文法の解説:Elm入門ハンズオン>
https://gitpitch.com/ababup1192/elm-handson2/master?grs=github&t=sky

by @ababup1192さん

 

自分の場合はさらに悩みをツイートしていたら @miyamo_madokaさん、@ababup1192さんに拾ってもらったので疑問点を聞いたりしていました。


主な機能や悩みどころ


ランダム値から16進数への変換

https://package.elm-lang.org/packages/rtfeldman/elm-hex/latest/

これを使いました。

elm install rtfeldman/elm-hex 
パッケージのインストールをします。

   

import Hex exposing (..) 
importして読み込ませます。

 

toHex : Int -> String 
toHex num = 
    let 
        hexString = 
            Hex.toString num 
 
        hexWithZero = 
            "00000" ++ hexString 
    in 
    String.right 6 hexWithZero 
実際には関数toHexを作成しました。

hexString

取得したランダム値を16進数のstringに変換します。

hexWithZero

カラーコードは6桁でならなければならないため、頭に0をつけて右から6桁までをカラーコードとしています。

例)hexStringが 12 → 000012 を取得


JSとのやりとり

JSとやりとりをする方法は以下の2つがあります。

  • flags
  • ports
flagsは初期化時に処理を加えるもので、今回のような

ランダム値を作成→JSに送る→Firebaseに保存

というものには適さないのでportsを使用しました。

portsについては公式ドキュメントに書かれているものの、型定義までで詳しい使い方のサンプルコードはないので以下の記事を参考にしました(ちょっと古いですが)。
https://qiita.com/boiyaa/items/c5670817f17938b7a755


Firebaseからのデータ設定・取得

https://firebase.google.com/docs/firestore/manage-data/add-data
https://firebase.google.com/docs/firestore/query-data/get-data

データ設定・取得はこれらを参考にしました。

  • コレクション:elm
  • ドキュメント:txt
という名前にしています。

const docRef = firestore.collection("elm").doc('txt'); 
 
docRef.get().then(function(doc) { 
    if (doc.exists) { 
 
      var app = Elm.Main.init({ 
        node: document.getElementById('elm') 
      }); 
 
      //JS to Elm 
      app.ports.fromJs.send(doc); 
 
      //Elm to JS 
      app.ports.toJs.subscribe(function(str) { 
          docRef.set({ 
            data: str 
          }); 
      }); 
 
    } else { 
        // doc.data() will be undefined in this case 
        console.log("No such document!"); 
    } 
}).catch(function(error) { 
    console.log("Error getting document:", error); 
}); 
Firebaseのドキュメント内に書かれていたサンプルコードをもとにElmコードを入れるとこのようになります。

しかし、これでは doc.exists の判定が終わるまで何も画面に表示されないという現象が発生します。(体感では2秒程度)

さすがに2秒は時間がかかりすぎなので基本的な内容は表示させておいて更新部分だけRESTで取得することにしました。

REST

https://firebase.google.com/docs/firestore/reference/rest/v1beta1/projects.databases.documents/get


これを参考にREST側のエラーメッセージを見ながら試行錯誤しつつ取得しました。

https://firestore.googleapis.com/v1beta1/projects/【プロジェクト名】/databases/(default)/documents/elm/txt


Typeとtype alias

公式ドキュメントにある Json と Random で Model の書き方が違っているため組み合わせた方法を知りたくなりました。

Json
type Model 
  = Failure 
  | Loading 
  | Success String 
Random
type alias Model = 
  { dieFace : Int 
  } 
https://guide.elm-lang.org/types/custom_types.html

に組み合わせた書き方が書かれていたので参考にしました。

さすが公式ドキュメント!

type Stat 
    = Loading 
    | Success 
    | Failure 
 
 
type alias Model = 
    { randomNumber : Int 
    , stat : Stat 
    } 
最終的にはこのようにして落ち着きました。


振り返り

  • 迷ったらとにかく公式ドキュメント。大抵の悩みはこれを見ればだいたい解ける!
  • それでも困ったらツイッターやdiscordで聞こう。すごいエンジニアさんがたくさんいます。
  • あと必要なのは英語力。でもGoogle翻訳と英文をにらめっこするのもアリ。でもGoogle翻訳は誤訳もあるので・・・


感想

Elmは前提として関数型の使い方とElm Architectureという独特なフレームワークに慣れないといけないという問題がありますが、慣れてくれば非常にやりやすいと感じました。

一番はなんといっても「No runtime errors」。基本的にランタイムエラーが無く、起きたとしてもJS側で読み込みさせるとかのJS連携させている場合のみです。なのでコンパイルさえ通れば安心して使えるというのが強みです。エラーがなければそれだけ調査とかに使う時間も減らすことができます。

今回はFirebaseとの簡単な連携をさせました。Elmでできる処理は全てElmにまわしているのでFirebase側の処理が最小限でできました。


Firebaseは非常に強力で便利なのですが非同期での取得が基本なので複雑になりがちです。JSだけでタスク管理ツールを作成したことがありますが、データ処理が複雑になりすぎて途中で改良を加えようとしたら全面的に修正を施す必要が出てきて心が折れたことがあります。

Elmはこういう複雑極まりないJSだけのアプリケーションの複雑度を下げるアプリケーションとして非常に有用なのではないかと思いました。最終的にはJSに吐き出すので当然JSでどのような動きをさせることができるかという知見は今までと同様に使えますし、基本文法も他の関数型プログラミング言語に比べれば簡単なので使ってみてはいかがでしょうか。

コメント

このブログの人気の投稿

投稿時間:2021-06-17 22:08:45 RSSフィード2021-06-17 22:00 分まとめ(2089件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)