ElmでFirebase認証とFirestoreを写経してみる
ElmとFirebaseでTODOアプリを作りたいのですが、とりあえず、以下のサイトを写経してみたいと思います。
https://qiita.com/ababup1192/items/f27f9af282d9fa642eb5
- 1. 開発環境
- 2. 新規Firebaseプロジェクトを作成
- 3. FirebaseでGoogle認証を有効にする
- 4. Firestoreデータベースの初期設定
- 5. FirebaseをWEBアプリから利用するための初期設定
- 6. 新規create-elm-appアプリの作成
- 7. public/index.htmlの編集
- 8. src/index.jsの編集
- 9. src/Main.elmの編集
- 10. portの追加
- 11. MODELの編集
- 12. PROGRAMの編集
- 13. UPDATEの編集
- 14. VIEWの編集
- 15. いろいろ調整
- 16. うまくいかないので、元のソースコードをダウンロードして、FirebaseConfigのみ書き換えて実行
- 17. Netlifyにデプロイ
- 18. 今回写経したサイト
- 19. Elmでお勧めのサイトと本
開発環境
Windows 10 Pro
Chrome
VisualStudioCode 1.32.3
git version 2.20.1.windows.1
nvm 1.1.7
node 10.2.0
npm 6.4.1
elm 0.19.0-bugfix6
elm-format 0.8.1
VisualStudioCodeの拡張機能でelmをインストールして、settings.jsonに以下のようにelmを設定。
(『Alt + Shift + F』と『Ctrl + S』を使用。)
"[elm]": {
"editor.formatOnSave": true
},
新規Firebaseプロジェクトを作成
Googleアカウントがなければ作成し、
https://console.firebase.google.com/
へログインして、新規プロジェクトを作成します。
今回は、firestore-auth という名前にしました。
下の方のチェックボックスをONにして、『プロジェクトを作成』をクリックします。
以下のような画面になります。
FirebaseでGoogle認証を有効にする
Google認証ができるように設定します。以下の2つのことを行います。
- プロジェクトでGoogle認証を有効にする
- 特定のアドレスからGoogle認証を有効にする(承認済みドメインの設定)
まず、画面左上の方の、『Authentication』をクリック
『ログイン方法』をクリック
Google をクリック
次のような画面になるので、『有効にする』をONにして、プロジェクトのサポートメールのところをクリックして、登録されたGmailアドレスを選択します。(私の場合は1個しか選択できませんでした。)
画面右下の『保存』をクリック。
以上で、このプロジェクトでGoogle認証が有効になりました。
特定のアドレスからGoogle認証を有効にする(承認済みドメインの設定)(localhostからはデフォルトで有効になっています。)方法は、またデプロイ先のホームぺージアドレスが決定してから、設定したいと思います。
Firestoreデータベースの初期設定
Firebaseのデータベースには
- Realtime Database
- Firestore
の2つがありますが、今回は、Firestoreを用います。
画面の左上の方の、『Database』をクリックします。
Cloud Firestoreの『データベースの作成』をクリック。
そのまま、『有効にする』をクリック
参考: https://qiita.com/sgr-ksmt/items/1a731fdadf06119d35fc
@sgr-ksmt
2018年12月12日に更新
Firestore rules tips
Firebaseで認証されたアカウントからのみ、Firestoreのデータベースをread & writeできるように、Cloud Firestoreセキュリティールールを変更します。
画面上の方の、『ルール』をクリックします。
以下のような画面になるので、
allow read, write: if false;
を以下のように書き換えます。
allow read, write: if request.auth != null;
(変更前)
(変更後)
その後、図のように、『公開』をクリックします。
後で、アプリからデータベースがどのように変更されたかを見るときは、『Database』>『データ』の順にクリックしていくと、見ることができます。
FirebaseをWEBアプリから利用するための初期設定
画面左上の『Project Overview』をクリック。
図のように、『</>』ボタンをクリックします。
アプリのニックネームに適当な名前を入力し、Firebase HostingのチェックボックスはOFFのまま、『アプリを登録』をクリック。
今回は、elm-foo というニックネームにしました。
以下のような画面になるので、グレーの部分の中身を、メモ帳などにテキストファイルとしてコピーしておきます。後で、Elmアプリの一部に記載します。
新規create-elm-appアプリの作成
C:/elm/ フォルダをVisualStudioCodeで開き、Ctrl+@でターミナル画面を開き、以下を入力します。
npm install create-elm-app -g
create-elm-app elm-firestore-foo
cd elm-firestore-foo
elm-app start
create-elm-app@3.0.6 がインストールされました。
参考: https://github.com/halfzebra/create-elm-app
public/index.htmlの編集
public/index.htmlの<body>タグ内の後ろのほうに以下を入力します。(上記のFirebaseのグレーの部分の一番上の部分)
<!-- The core Firebase JS SDK is always required and must be listed first -->
<script src="https://www.gstatic.com/firebasejs/6.0.2/firebase-app.js"></script>
(変更前)
(変更後)
この後、なんとなく、コピペ元の、以下に変更しました。
<script src="https://www.gstatic.com/firebasejs/5.8.3/firebase.js"></script>
蛇足ですが、bulmaとFontAwesomeを使用したい場合は、
http://i-doctor.sakura.ne.jp/font/?p=36580 をご覧ください。
src/index.jsの編集
引き続き、 https://github.com/ababup1192/elm-firebase/blob/master/src/index.js を写経していきます。
src/index.jsに、firebaseConfigや、elm用のportなどを記載していきます。
const config = {} の中身は、上記のFirebaseの初期設定でのグレーの部分のご自身のアプリのデータをコピペしてください。
const app = Elm.Main.init();
const config = {
apiKey: "<YOUR-API-KEY>",
authDomain: "<YOUR-APP>.firebaseapp.com",
databaseURL: "https://<YOUR-APP>.firebaseio.com",
projectId: "<YOUR-APP-ID>",
storageBucket: "<YOUR-APP>.appspot.com",
messagingSenderId: "<YOUR-APP-SENDERID>"
};
firebase.initializeApp(config);
const provider = new firebase.auth.GoogleAuthProvider();
const DB = firebase.firestore();
// ログイン監視
firebase.auth().onAuthStateChanged((user) => {
if (user) {
app.ports.signedIn.send(true);
// ログイン後にDatabase監視
DB.collection('foo').doc(user.uid).onSnapshot((doc) => {
const data = doc.data();
app.ports.read.send(data.input);
});
}
});
app.ports.signIn.subscribe(_ => {
firebase.auth().signInWithPopup(provider).then((_) => {}).catch((error) => {});
});
app.ports.push.subscribe(text => {
const user = firebase.auth().currentUser;
DB.collection('foo').doc(user.uid).set({input: text});
});
(変更前)
(変更後)
src/Main.elmの編集
MODEL, UPDATE, VIEWの順に写経していきたいと思います。変更前は、以下のようになっています。
portの追加
最初の方を、以下のように書き換えます
port module Main exposing
( Model
, Msg(..)
, init
, main
, read
, signedIn
, update
, view
)
import Browser
import Browser.Navigation as Nav
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Http exposing (Error(..))
import Json.Encode as E
-- ---------------------------
-- PORTS
-- ---------------------------
port signIn : () -> Cmd msg
port push : String -> Cmd msg
port read : (String -> msg) -> Sub msg
port signedIn : (Bool -> msg) -> Sub msg
elm/json パッケージをインストールします。VisualStudioCodeのターミナル画面(Ctrl+@で表示)で、以下を入力します。
elm install elm/json
elm/http パッケージをインストールします。VisualStudioCodeのターミナル画面(Ctrl+@で表示)で、以下を入力します。
elm install elm/http
その後、一度、Ctrl+Cでサーバを停止して、elm-app startでサーバを起動すると、以下のようになります。
MODELの編集
今回必要なMODELは、以下の2つとなりますので、それらを記載します。
- 入力するテキストpushText
- Google認証でサインインしているかどうかisSignedIn
---- MODEL ----
type alias Model =
{ pushText : String
, isSignedIn : Bool
}
init : () -> ( Model, Cmd Msg )
init isSignedIn =
( { pushText = "", isSignedIn = False }, Cmd.none )
PROGRAMの編集
subscriptionsでindex.js(Javascript)からの"read"と"signedIn"ポートを受け取るために、以下のように変更します。
---- PROGRAM ----
main : Program () Model Msg
main =
Browser.element
{ init = init
, update = update
, view = view
, subscriptions = subscriptions
}
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.batch [ signedIn SignedIn, read Read ]
(変更前)
(変更後)
UPDATEの編集
よくわかっていないけど、とりあえず写経です。Modelを考えるのは比較的簡単ですが、Msgは、自分で思いつける気がしません。。。
とりあえず今回のMsgとしては、以下の4つのようです。
- SignIn : ElmからFirebaseにサインインの申し込みをする(?)
- Push : Elmで入力したテキストをFirebaseに送る
- Read : FirebaseのテキストをElmで受け取る
- SignedIn : FirebaseからサインインできたことをElmで受け取る
これがよくportのところで説明されている、
『 Elm と JavaScript は、ポートを通じて互いに一方的に送信を行うことで、通信をすることができる 』
っていうやつなんでしょうか。。。
---- UPDATE ----
type Msg
= SignIn
| Push String
| Read String
| SignedIn Bool
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
SignIn ->
( model, signIn () )
SignedIn isSignedIn ->
( { model | isSignedIn = isSignedIn }, Cmd.none )
Push text ->
( { model | pushText = text }, push text )
Read text ->
( { model | pushText = text }, Cmd.none )
(変更前)
(変更後)
VIEWの編集
見栄えを調整しようとすると心が折れるので、また後で、、、
---- VIEW ----
view : Model -> Html Msg
view { pushText, isSignedIn } =
div [ class "container" ]
[ img [ src "/logo.svg" ] []
, h1 [] [ text "Your Elm App is working!" ]
, button [ onClick SignIn ] [ text "Google サインイン" ]
, if isSignedIn then
input [ type_ "input", value pushText, onInput Push ] []
else
text ""
]
(変更前)
(変更後)
いろいろ調整
Googleサインイン ボタンをクリックしてみると、ログインできるでしょうか?
ログインすると、Googleサインイン ボタンの右側にINPUTボックスが現れて、、、を期待していましたが、そう甘くはなく、以下のようなエラーになってしまいました。
Firestoreを見てみます。
試しに、『コレクションを追加』で、foo を追加してみます。
自動ID をクリックしてから、保存 をクリックします
これでもダメでした。
その後、FirebaseのAuthenticationからログインユーザの『ユーザーUID』をコピーして、foo コレクション下のdocument名として登録し、さらにその下に input: “foo2″ と入れて、ようやくアプリが動きましたが、これは明らかにおかしい動き、、、firebaseのバージョンの5と6の違い、もしくは、Browser.documentをBrower.elementで代用したことが原因にあるのかもしれませんが、よく分かりません。。。
(2019/5/11追記)developmentモードでは、赤いエラーが出るのですが、エラーの右上の×ボタンをクリックすると、普通にいけました。create-elm-appをNetlifyにデプロイする方法はやや面倒(参考: http://i-doctor.sakura.ne.jp/font/?p=36506 )ですが、PWA(Progressive Web Apps)として、スマホでサイトを訪問すると、「ホーム画面に追加」が出てきて、すぐにインストールすることができます。
DEMOサイト(create-elm-app版): https://zen-thompson-04a101.netlify.com/
---- VIEW ----
view : Model -> Html Msg
view { pushText, isSignedIn } =
div []
[ nav [ class "navbar has-background-info" ]
[ div [ class "navbar-brand" ]
[ a [ class "navbar-item has-text-white", href "#" ] [ text "elm firestore foo" ]
]
]
, section [ class "section" ]
[ div [ class "container" ]
[ img [ src "/logo.png" ] []
, br [] []
, a [ class "button is-success", onClick SignIn ] [ text "Google サインイン" ]
, br [] []
, div [ class "columns is-centered" ]
[ div [ class "column is-half" ]
[ if isSignedIn then
input [ class "input", type_ "input", value pushText, onInput Push ] []
else
text ""
]
]
]
]
, footer [ class "footer" ]
[ div [ class "content has-text-centered" ]
[ p []
[ a [ href "http://i-doctor.sakura.ne.jp/font/?p=37747" ] [ text "WordPressでフリーオリジナルフォント2" ]
]
]
]
]
うまくいかないので、元のソースコードをダウンロードして、FirebaseConfigのみ書き換えて実行
(2019/5/11追記) 当初はcreate-elm-app版はあきらめて、 以下のように実行してみました。
https://github.com/ababup1192/elm-firebase
からZIPファイルをダウンロードして、src/index.jsの
const config = { }
の中身だけ自分のFirebaseのconfigに変更して、
npm start
したら、思った結果になりました、、、が、原因はよく分からず。。。
Netlifyにデプロイ
BitBucketにgit pushして、BitBucket経由でNetlifyにデプロイします。
DEMOサイト:https://cranky-hugle-2eb592.netlify.com/
このまま Googleサインイン をクリックしてもうまくいかないので、
https://console.firebase.google.com
において、Authentication > ログイン方法 で、『承認済みドメイン』に、上記アドレスを追加します。
すると、上記のnetlifyにデプロイしたWEBアプリ上からも、Google認証ができるようになります。
上記のように文字を入力すると、ちゃんと、Firestoreにも登録されているようです。
なお、こちらの方は、デフォルトではPWA化はされていません。(少し頑張れば、PWA化できるのだとは思いますが、、、)
今回写経したサイト
https://qiita.com/ababup1192/items/f27f9af282d9fa642eb5
Elmでお勧めのサイトと本
https://guide.elm-lang.jp/
Elm公式サイトの日本語訳です。
ディスカッション
コメント一覧
まだ、コメントがありません