Elm で作ったもんを Firebase に手動でデプロイ

Elm アプリを Firebase にデプロイするのちょこちょこ見るんで自分もやったろ！と思い立ってやったことのメモ。
Elm 分が少なすぎて割とタイトル詐欺。
「Firebase 静的サイト」でググって出てくるページと大体同じ感じに…そういうこともあります。

最終的に公開されるものはこんな感じ (PC用。スマホでも見られるが表示が小さい) 。

- https://elm-book-memos-with-del-button.firebaseapp.com
  - モノは [基礎からわかるElm](http://www.c-r.com/book/detail/1299) P.118-123 のフォーム入力アプリ


## 前提 (やってあったこと)

- GitHub への Elm ソースのプッシュ
  - https://github.com/ossan-pg/elm-book-form-input/tree/delete_memo_button
- Node.js (npm) のインストール
- Elm のインストール


## 手順 (やること)

- Firebase へのユーザ登録
- Firebase プロジェクトの作成
- Firebase CLI のインストール＋ログイン
- ソースの取得
- プロジェクトディレクトリの初期化
- ソースのビルド
- デプロイ

各作業を人の手による温かみを感じる昔ながらの方法でやっていきます。


## Firebase へのユーザ登録

あまり覚えてないので割愛します。
メールアドレスを登録して特に困ることなく進んだ気がする。


## Firebase プロジェクトの作成

資材のデプロイ先を用意します。

[Firebase コンソール](https://console.firebase.google.com/) を開きます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/73432/f9e915c1-6fe9-148a-42c2-242f4c37d783.png)

(既に目的のプロジェクトが作られてるけど気にしない)

「プロジェクトを追加」をクリックします。
「プロジェクトの追加」ウィンドウが開くので各項目を入力していきます。

「プロジェクトID」と「Cloud Firestore のロケーション」は後で変更できないので本格運用する場合は気を付けましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/73432/d9615749-25ea-3f09-58e7-05d1f0fbbf85.png)

「プロジェクトを作成」ボタンをクリックしてプロジェクト作成処理を実行します。
作成が完了するとそれを知らせるウィンドウが表示されるので「次へ」ボタンをクリックしましょう。
「Project Overview」のページへ遷移します。
とはいえ、今のところはこのページでやることは特にないです。次へ進みます。


### 余談：プロジェクトの削除

プロジェクトの削除はプロジェクトの設定画面からできます。
ただし、プロジェクト復元のための保留期間が 30日あります。
言い方を変えると完全に削除されるまでには 30日かかります。

「削除すればいいや」と思ってお試しでテキトーなプロジェクトを作ってしまうと、最低30日はそのプロジェクトが存在することになるので注意しましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/73432/86508b38-59c0-f625-f9d9-24ca8aa56799.png)

やってしまった…。


## Firebase CLI のインストール＋ログイン

ここからはローカルでの作業です。
[Firebase CLI リファレンス](https://firebase.google.com/docs/cli/?hl=ja) を参考に進めます。

```bash:インストール
$ npm install -g firebase-tools
```

```bash:ログイン
$ firebase login
```

コマンド実行後にウィンドウが表示されるのでユーザ情報を入力していきます。
ウィンドウが表示されるまで少し時間がかかるかも。


## ソースの取得

ソースを用意できれば取得元はどこでもよいです。
今回は GitHub にプッシュしておいたソースを取得します。

```bash:ソースの取得ついでにディレクトリも作成
$ cd <任意のディレクトリ>
$ git clone https://github.com/ossan-pg/elm-book-form-input.git -b delete_memo_button elm-book-with-del-button
```

master ではないブランチのものをデプロイしたかったので `-b` でブランチを指定しています。


## プロジェクトディレクトリの初期化

今回は `git clone` で作成したディレクトリをそのまま Firebase のプロジェクトディレクトリとしました。
やらなきゃよかった。

`clone` してきた `.gitignore` が既に存在するため、ここで実施する `firebase init` により本来作成されるはずの Firebase 用 `.gitignore` が作成されません (既存の `.gitignore` を上書きしません) 。
今回の手順では Firebase 関連のファイルを Git で操作する作業はないので「まぁええやろ」と思ってたんですがやっぱりよくなかったです。
`.gitignore` を抜きにしても Firebase と Elm のファイルが混在して何が何やらになります。
次やるときはディレクトリをちゃんと分けよう。

```bash:プロジェクトディレクトリの初期化
$ cd ./elm-book-with-del-button
$ firebase init
```

`firebase init` を実行するとプロジェクトに必要な設定や確認事項を訊かれるのでそれぞれ答えていきます。

```text:準備の確認
? Are you ready to proceed? (Y/n) 
```

準備ができているかの確認です。
そのままエンターして Yes を選択します。

```text:featureの選択
? Which Firebase CLI features do you want to setup for this folder? Press Space to select features, then Enter to confirm your choices.
 ( ) Database: Deploy Firebase Realtime Database Rules
 ( ) Firestore: Deploy rules and create indexes for Firestore
 ( ) Functions: Configure and deploy Cloud Functions
>( ) Hosting: Configure and deploy Firebase Hosting sites
 ( ) Storage: Deploy Cloud Storage security rules
```

使いたい feature を選択します [^2] 。
今回はホスティングだけでいいので `Hosting` にチェックを入れてエンターします。

[^2]: feature ってどう訳すのがいいんだろ。

```text:プロジェクトとの関連付け
=== Project Setup

First, let's associate this project directory with a Firebase project.
You can create multiple project aliases by running firebase use --add,
but for now we'll just set up a default project.

? Select a default Firebase project for this directory:
  [don't setup a default project]
  fir-demo-project (Firebase Demo Project)
> [create a new project]
```

作業ディレクトリ (カレントディレクトリ) と関連付ける Firebase プロジェクトを選択します。
デモプロジェクト `fir-demo-project` は Firebase コンソールで「デモプロジェクトを見る」を実施していると表示されます。

一方で作成したプロジェクト `elm-book-memos-with-del-button` が表示されてません。なぜ… :cry: 。
`firebase use --add` で設定できるよ的なことも言ってるので、ここでは一旦 `[create a new project]` を選択 [^3] して先へ進めます。

[^3]: `[don't setup a default project]` を選択した場合でも生成されるファイルやディレクトリは `[create a new project]` と全く同じ。ホスティング以外を選択すると変わってくるのかもしれない。未調査。

```text:デプロイ用の資材を配置するディレクトリ
=== Hosting Setup

Your public directory is the folder (relative to your project directory) that
will contain Hosting assets to be uploaded with firebase deploy. If you
have a build process for your assets, use your build's output directory.

? What do you want to use as your public directory? (public)
```

デプロイ用の資材を配置するディレクトリを指定します。
デフォルトでは `public` という名前のディレクトリが作業ディレクトリ内に作成されます。
別の名前がよい場合は適宜入力しましょう。
`foo/bar` のような指定も有効で、この場合は `foo` ディレクトリとその中に `bar` ディレクトリが作られます。

今回は `public` でよいのでそのままエンターします。

```text:SPAにする？
? Configure as a single-page app (rewrite all urls to /index.html)? (y/N)
```

そのままエンターして No を選択します。
SPA な作りにしたい場合は `y` を入力しましょう。

ちなみに Yes と No のそれぞれ選択した時の違いを調べてる方がいたので詳しくはそちらの記事を参考にしましょう。

- [firebase init 時に聞かれる「Configure as a single-page app (rewrite all urls to /index.html)?」は選択によって何がどう変わるのか](https://qiita.com/megane42/items/96356a88d67fcc1499ee)

これで `firebase init` は完了です。
ここまでで作業ディレクトリ内のファイルやディレクトリは下記のような感じになっています。

```text:作業ディレクトリ内
elm-book-with-del-button/
 |-- .firebase/
 |-- .firebaserc
 |-- .git/
 |-- .gitignore
 |-- README.md
 |-- elm-stuff/
 |-- elm.json
 |-- firebase.json
 |-- public/
 |    |-- 404.html
 |    `-- index.html
 `-- src/
      `-- FormInput.elm
```

うわぁ… :innocent: (前述の通りディレクトリちゃんと分ければよかった) 。

気を取り直して、次に実施する作業が表示されている [^4] のでそれを確認しましょう。

[^4]: ここのメッセージはディレクトリとプロジェクトの関連付けで `[create a new project]` を選択した場合のみ表示される。`[don't setup a default project]` を選択した場合は表示されない。

```text:次の作業
Project creation is only available from the Firebase Console
Please visit https://console.firebase.google.com to create a new project, then run firebase use --add
```

Firebase コンソールでのプロジェクト作成は既に済んでいるので `firebase use --add` を実行してプロジェクトと関連付けします。

```text:プロジェクトの選択
$ firebase use --add
? Which project do you want to add? (Use arrow keys)
> elm-book-memos-with-del-button
  fir-demo-project
```

`elm-book-memos-with-del-button` を選択します。

```text:エイリアス名の設定
? What alias do you want to use for this project? (e.g. staging)
```

作業ディレクトリ内で扱うプロジェクトを示すエイリアス名を設定します。
プロジェクトのエイリアスについては [Firebase CLI リファレンス](https://firebase.google.com/docs/cli/?hl=ja) の「プロジェクトエイリアスを管理する」が詳しいので目を通しておきましょう。

設定する名前は何でもいいですが、ここではデフォルトのプロジェクトを示す `default` にします。
本来であれば `? Select a default Firebase project for this directory:` のところでデフォルトのプロジェクトを設定できたはずなのですが、うまくできなかったのでここで設定しておきます。

エイリアスの設定が終わると `.firebaserc` の内容が下記のようになります。

```json:.firebaserc
{
  "projects": {
    "default": "elm-book-memos-with-del-button"
  }
}
```

## ソースのビルド

Elm のソースファイルをビルドします。
出力先は `public/index.html` にします。

```bash:ソースのビルド
$ elm make src/FormInput.elm --output=public/index.html
```

`Success!` が表示されれば OK です。


## デプロイ

`public` ディレクトリ内の資材をデプロイします。

```bash:デプロイ
$ fireabase deploy
```

`Deploy complete!` が表示されれば OK です。

Firebase コンソールのプロジェクトページとアプリのアドレスが表示されているのでアクセスして確認してみましょう。

```bash
Project Console: https://console.firebase.google.com/project/elm-book-memos-with-del-button/overview
Hosting URL: https://elm-book-memos-with-del-button.firebaseapp.com
```


## おわり

ホントは [elmで作ったものを、GitHubActionsを使って自動でFirebaseにデプロイするまでの手順](https://qiita.com/Goryudyuma/items/8ed041b1ea0be87c0c20) をやってみたかったんですが、GitHub Actions を申請しておらず試せませんでした (申請したもののいつ申請通過するか不明) 。
申請が通ったら今回のことを踏まえて再度試してみようと思います。

あと初めて触れましたが Firebase 楽ですね。
本格的にやると色々あるかもしれませんが「やったろ！」と思ってからアプリ公開までの経験をサクッと得られるのは好感触でした。