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)
作成したアプリについて
クリックするとランダムで背景色が変わるというものです。これではわかりづらいですがランダム値は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 (..)
toHex : Int -> String toHex num = let hexString = Hex.toString num hexWithZero = "00000" ++ hexString in String.right 6 hexWithZero
hexString
取得したランダム値を16進数のstringに変換します。
hexWithZero
カラーコードは6桁でならなければならないため、頭に0をつけて右から6桁までをカラーコードとしています。
例)hexStringが 12 → 000012 を取得
JSとのやりとり
JSとやりとりをする方法は以下の2つがあります。- flags
- ports
ランダム値を作成→JSに送る→Firebaseに保存
というものには適さないのでportsを使用しました。
portsについては公式ドキュメントに書かれているものの、型定義までで詳しい使い方のサンプルコードはないので以下の記事を参考にしました(ちょっと古いですが)。
https://qiita.com/boiyaa/items/c5670817f17938b7a755
Firebaseからのデータ設定・取得
https://firebase.google.com/docs/firestore/manage-data/add-datahttps://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); });
しかし、これでは 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 }
に組み合わせた書き方が書かれていたので参考にしました。
さすが公式ドキュメント!
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でどのような動きをさせることができるかという知見は今までと同様に使えますし、基本文法も他の関数型プログラミング言語に比べれば簡単なので使ってみてはいかがでしょうか。
コメント
コメントを投稿