Webアプリ無料運営のススメ：FirebaseとNuxt(Vue)なら最強！

まだサーバーで消耗してるの？Firebase（サーバーレス）とNuxt.js（Vue系）ならWebアプリ運営は最強でしょ！？

この記事は、

- **サーバー費用をなるべくかけたくない**けどショボいのはNO
- **Firebaseの活用法**をあまり理解していない
- **Nuxt/Vue**を使って**アプリ作ってみたい**（Next/Reactと悩んでたり）
- アプリ構想はあるけど**アイデアの落とし込みスピードが遅くて毎回挫折する**

という人向けに、**「こんな感じで構築すれば効率良く開発できそうよ」**というのを、**勉強になった記事**や**技術的トピック・躓いた点**なども合わせて紹介させていただきます。**初心者向け＆技術トピック気になる方向**けです！

# 今回作ったアプリ「Moji → Pic」
[**Moji → Pic**](https://mojipic.f-arts.work/)は、文字だけだとなかなか目につく投稿ができないなぁ…とお困りの時に**インパクトある画像が即座に出来るアプリ**。目立ったツイートで**友達に差をつけろ！**

[![animel-all.gif](https://qiita-image-store.s3.amazonaws.com/0/262161/efaf730e-e012-2bb6-6dea-2007a2b40ff9.gif)](https://mojipic.f-arts.work/)

### 提案手法の優位性
**既存手法 :worried:**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/262161/c7202315-c631-dcaa-0bfe-9a146efffb4c.png)


**提案手法 :tada:**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/262161/ba4792f8-f423-ccd1-881d-846a7d2e976d.png)

そんな感じで、他人の金で肉や寿司が食べたいときにでも使ってみて下さい。無為なツイートがもっと無為になることでしょう。
**ログインしなくても画像作ったりDL出来たり楽しめる**ので、是非遊んでくださいませ。

[**Moji → Pic：思いっきり伝えよう**](https://mojipic.f-arts.work/)

[GIGAZINEでも紹介](https://gigazine.net/news/20190224-mojipic/)いただきました！！サービスについて私よりわかりやすくまとめていただいたので、こちらも是非御覧ください。


### 今回のトピック

:ballot_box_with_check: **基本技術トピック**：FirebaseとNuxtが凄いところ

- Firebaseの力で**複数プラットフォーム**でログイン可能に（Twitter・Google・Facebook）
- NuxtのSSR機能のお陰で、**投稿画面をSNSにシェア**すると、**各投稿毎にOGP画像が設定**されている
- Firestore・storageのルール設定をすれば**ユーザ毎の細かな権限を設定**できる

:ballot_box_with_check: **応用技術トピック**：このアプリの工夫ポイント

- 全部SSRはFirebaseのFunction通すとレスポンス悪いと石を投げられるので、**SSRしたい動的ページ以外は静的ページとして配信**
- FirebaseでのTwitterログイン機能から**アクセストークンを取得し、Twitter投稿**をする

:ballot_box_with_check: **残念トピック**：改善したいポイント

- プラグインが多くてロードが遅いのでなんとかしたかった話

このあたりの内容を入れてお送り致します。

このアプリ制作では、オレオレルールですが、**「5秒でログイン、30秒で投稿」**を肝に銘じ作りました。UXデザインに通じているわけではないので虚言甚だしいですが、どんなに良いアプリでも「**導線が上手く出来てないアプリは死ぬ**」「**機能の詰めすぎ悲しいかなエンジニアのエゴ**」などを常に意識しながら最近は生きています。ちなみにこのアプリがそれを体現できているかは実際に見に行って見て下さい（石は投げないで下さい）。

そういう意味では、Firebaseを使って構築ってなると、**Firebaseの機能をそのままサクっと使いたい**ので、**ミニマルでシンプル構成に引っ張られやすい**のも、私はメリットだと感じています。（もちろん複雑なアプリも出来る…！）

# はじめに
## 自己紹介
モノづくりをしたりプログラミング先生をやったり。最近は、Railsで[**歌声専門フリマサイト**](https://utaile.com/)とか、React勉強で[**今期アニメ検索アプリ（Qiita記事）**](https://qiita.com/y_kawase/items/8f1b5a303400a09c4923)とか作ったりしました。

また、Web系言語やらのネタで[**ブログにTIPS**](https://blog.f-arts.work/)をたとめていたり、[**Twitter(@y_kawase)**](https://twitter.com/y_kawase)でもちょこちょこ真面目ネタも呟いているので宜しければ絡んで下さい。

**直接ビデオ通話で技術系相談したいぞ**という方は、[**こちら**](https://menta.work/plan/933)にも登録しておりますので、も良ければご活用下さい。答えられることなら何でも答えます。 → https://menta.work/plan/933


## アジェンダ
前半はわりと基本的な内容や紹介なので、技術的な内容で気になる方は後半をご覧下さい。

1. 経緯と小話
    - 小規模・個人開発こそ「コスト・機能・効率が良い開発を」
    - FirebaseとNuxtで開発スピードアップ「初中級者こそ率先して使うべし」
2. 技術要素のお話
    - 全体構成
    - Firebase（サーバーレス）はいいぞ
    - Nuxt（Vueフレームワーク）はいいぞ
    - Buefy（CSSフレームワークBulma in Vue）はいいぞ
    - Konva（Canvas描画系ライブラリ）はいいぞ
    - Google Fontsはいいぞ
3. 技術トピック（TIPS・躓いた点など）
    - Firebaseのルールの書き方：ユーザ毎の権限を付与＆リファレンス参照
    - firebaseapp.comドメインを使用不可にしたいけどダメそう
    - FirebaseのTwitterログインからアクセストークンを取得する
    - SSRしたいページ以外は静的ファイルで配信したい
    - 本番ではconsole.logの表示をしないようにする
    - emoji-martが重いのと変な挙動が
    - konvaの文字配置は環境差分がありそう
    - プラグインが多くてページ読込が遅いのでつらい

私自身も勉強中の身ですので不備不足はご容赦下さい。**情強の方のアドバイス・ご指摘など大歓迎**です…！\:ok_woman:\:ok_woman:\:ok_woman:

## 経緯と小話
### 小規模・個人開発こそ「コスト・機能・効率が良い開発を」

最近すごく感じるのが、**小規模開発（個人開発含む）や趣味の場合、サーバーコストがサービス継続に影響している**という所です。

せっかく作ったし、いつかバズるんじゃねと思ってサービスを動かし続けてても、サーバーの維持費に**月500円（年間6000円）**かかるわけです。数年後アクセス解析をみて殆どアクセスなんてなかったんや…と途方に暮れながらサービスクローズする姿が私には見えます…（本当にあった怖い話）

そんなこともあり、最近は

- コスト：基本無料で利用量が一定量増えたら課金のFirebase
- 機能：Google様の加護Firebaseと、初心者でも触りやすいVue系のNuxt
- 効率：プラグイン豊富なNuxtでサクッと構築

という、**Nuxt.js（Vue.js）＋Firebaseが今一番身につけて損は無い技術**なんじゃないかと思った次第です。特に、このセットの記事は最近良く見かけることもありますので、**FirebaseとNuxtの2人なら最強！**ってことだと思ってます。

### FirebaseとNuxtで開発スピードアップ「初中級者こそ率先して使うべし」
鋭い方は覚えているかもしれませんが、以前私はVue系ではなく、**React**使ってました。いつの間にVue系に鞍替えしたのよという感じ。そうです、[**Reactで誰もがやりたかった10の機能。アプリ構想はあるけど作れない人の壁をぶっ壊す。**](https://qiita.com/y_kawase/items/8f1b5a303400a09c4923)という記事を書いたりして勉強していたのですが、その後いざSSR（サーバーサイドレンダリング）をしたくなってNext.jsに手を出しました…ただ悲しいかな私には難しすぎました…（特にstoreやthemeまわりの設定がしんどかった…）

ふと、**Nuxt.js**を触ってみることにしたところ、**便利プラグインやら簡単な設定**やらで、**初心者にとっては大変ありがたい仕組みが用意**してくれていました。後ほど技術要素のお話でも取り上げようと思いますが、「**store管理がデフォで入ってる**」「**Buefyテーマ（CSSフレームワーク）を読み込んでくれるプラグイン**」とかが**Nuxt用に最適化し用意されて**いて、使いたいものを設定ファイルに書けばすぐに動きました…Nuxtさん優しすぎる…

もちろん最終的にはそれぞれのフレームワークには確固たる方針があってメリットがあると思います。**React・Vue・Angular**が今のところは3大JSフレームワークと言われていて、それぞれメリットがあります。それぞれ素晴らしい特色があるのできちんとどれが良さそうか見定めると良いと思います！！
参考になりそう→[【JavaScript】３大フレームワーク Angular, React, Vue.jsを比べてみよう](http://iwasiman.hatenablog.com/entry/2018/04/23/200000)

個人的な意見として、**初心者がとりあえずサクッと構築したい**という場合は、**Vue.js/Nuxt.jsの方が日本語情報も多いですしとっつきやすそうだな**という感想です。GitHubのStar数はVue＞Reactになったし、ひとまずはVue系の時代がまだ続くでしょと思う。

あとは、**Nuxt界隈では@potato4dという神が君臨**しており、Vue・Nuxtまわりのお話をよくアウトプットしてくれるので、それも凄く心強いなと思っています。

## 技術要素のお話
### 全体構成
Nuxtバージョン：2.3.4
![Mojipic構成図.png](https://qiita-image-store.s3.amazonaws.com/0/262161/7ac6def6-c546-6b0b-ebd1-ca6d6e1aa68a.png)

[Draw.io](https://www.draw.io/)で作った雑な構成図で怒られそう。ポイントとしては静的ページは直接Hostingに配置したものを見に行って、動的ページはSSRのためにFirebaseのFunction越しに色々見に行っている感じ。ちなみに「SSR x Firebase」構成については詳しくはこのあたりの素晴らしい記事を読んでくれ。

　
**ーー追記ーー**
FunctionでのSSRは少し古い内容になります。先日（2019/4）に発表されたCloudRunを使ってSSRをするのが今後は主流になるかと思われます。
https://firebase.google.com/docs/hosting/cloud-run
　

[Nuxt.jsとFirebaseでSPA×SSR×PWA×サーバーレスを実現する](https://inside.dmm.com/entry/2018/04/10/nuxt-firebase)
[Nuxt.jsとFirebaseを組み合わせて爆速でWebアプリケーションを構築する](https://qiita.com/potato4d/items/cfddeb8732fec63cb29c)

~~TypeScriptで書くのもいいよね。私は今回は断念したけど。。~~
[【リンク切れ(2020/02)】TypeScript + Nuxt.js + Firebase (+ SSR)でWebアプリを構築](https://tamanyan.net/typescript-nuxtjs-firebase/)

### Firebase（サーバーレス）はいいぞ
#### サーバーレスとは
文字通りサーバーが無く、自分でサーバーを借りたり立ち上げたりする必要が無いということ。サーバーが常に待機状態にある従来と違い、アクセスされた瞬間に処理が走りアクセスが無い時はお休みをしているイメージです。
AmazonのAWSならLambdaなどがサーバーレス系で強かったイメージですが、最近はFirebaseがかなりグイグイ来ていますね。

普通のサーバー有りのものと違い、制約は多いですが（動かせる言語に限りがある、バージョンが指定されている等）、常時サーバーを動かさなくて済むため、コストが大幅にカット出来ます。

また、サーバーの場合は規模を大きくする際に、構成を増やしたり、その分通信経路を振り分けたり…とスケールアップが大変な部分がありますが、サーバーレス系の場合はこのあたりのスケールアップを勝手にやってくれる（1アクセスにつき1処理なので、アクセスが増えたら処理要員を増やせばいいだけ）ので、**インフラ系で悩むことから開放**されます。

#### Firebaseは最高だぜ
FirebaseはBaaSと言って、アプリケーションのバックエンドのサービスになります。サーバーレスの機構を使いやすくするために、

- 認証機能（Google、Facebook、Twitter、メールなど）
- DB機能（Firestore(NoSQL)）
- ストレージ機能
- ホスティング機能

など、とても便利な付随機能があります。

もちろん認証系に特化したサービス[Auth0](https://auth0.com/jp/)を使うとかも良いかとは思いますが、Firebaseですべてを完結できるので使わない手はないでしょう。

#### お値段もちろん無料から可能
そうなんです、**お値段なんと無料**です。すごい。 外部との通信などの場合はプランを有料プラン（Blazeプランという従量制プラン）に変更する必要はありますが、ご安心。**毎月の無料枠がかならずついている**ので、たいていの人は無料枠内に収まるのかとは思います。

なお、無料枠内は、Function呼び出しが12.5万回/月や、HostingのTransferが10GB/月とかなので、これを超えるサービスはもう無料枠の必要ないでしょという感じがあります。[Firebaseのお値段・プランなどは公式サイトで確認](https://firebase.google.com/pricing/?hl=ja)するといいです。

つまりサービス開始時はおそらくたいていはほとんど料金を払う必要が無く、ゆくゆくサービスが大規模化していった場合にようやくお金を払う、そんなシステムになっています。

バズってアクセスが集中した月だけお金を払うようなシステムなので、普段は音沙汰ないけど、突然有名人にRTされてアクセス集中してサーバーが落ちたなんてことはありません。これも小規模・個人開発ではありがたい点なのかなと思います。

### Nuxt（Vueフレームワーク）はいいぞ
先述の通りNuxtは色々なプラグインが豊富に用意されており、初心者にとっては大変使いやすい仕組みができています。またNuxtのベースになっているVueも初心者受けが良いと好評なツールですので、「**とりあえずNuxt&Vue**:beer:」で作ってみるのは良いんじゃないかなと思います。

ディレクトリ構成とかも既に決まっていたりするので、そういった制約が逆に構築しやすくなったりしたりします。

#### Vueについて
**そもそもVue.jsって何って人**はこのあたりを読んでおけばおｋ
[jQuery から Vue.js へのステップアップ](https://qiita.com/mio3io/items/e7b2596d06b8005e8e6f)

簡単に言うと、**JavascriptとHTML表示側の連携をすごくやりやすくしてくれている**ツール。入力が発生するアプリを作らないと実感わかないと思うのですが、純jsやjQueryで入力フォーム沢山＆フォーム入力イベント処理ありのアプリを作ると管理出来ない代物がもれなく出来るので死にます（私だ）。

[Vueの公式ドキュメント](https://jp.vuejs.org/v2/guide/index.html)がしっかりしているので、とっつきやすいです。日本語ドキュメントもあります（ちょっと最新バージョンには対応が遅いけど）

ちなみに、最近はTypescriptでVueを書くのも流行っているので気になる方はチェックしてみては如何でしょうか。[vue.js + typescript = vue.ts ことはじめ](https://qiita.com/nrslib/items/be90cc19fa3122266fd7)

ただ、Vueはクライアント側でレンダリングをするため、よく言われている話ですが、TwitterなどSNSでシェアした時に、投稿ページ毎のOGP画像などが反映されません（これはTwitter等では、レンダリングする前のデータを読み込んでいたりするため）。そこで、SSRという技術が必要になり、Nuxtが活躍したりします。

そういう意味では、**SNSでのシェア時、個別ページ毎にOGP設定とかタイトル設定とかしなくて良いよ**という方は、**Nuxt使わずにVueだけでも良い**と思います。


#### Nuxtについて
サーバーサイドレンダリングするための設定がすでにされているのでめっちゃ便利です。
[Nuxtの公式ドキュメント](https://ja.nuxtjs.org/guide/)もしっかりしているので大変分かりやすい。

ちなみに**Vueで十分だとか言う話も勿論ある**ので、それでOKな人は良いと思う。いわゆるSSR不要論というやつ。クローラーとかSEOとかそういう小難しいのは分からないので、私の判断基準は「**TwitterとかのSNSでURLがシェアされた時に、個別のサムネ画像を用意したいかどうか**」だ。一般的に**SNSにシェアしたりするWebサービス**を作る場合は、この**動的なサムネ画像（OGP画像）の設定が必要になるケースが多い**のでSSRはしておいたほうが良いと私は思う。普通SSRは面倒だけど全部Nuxtがなんとかしてくれるからね。

※ちなみにGoogleとかのクローリングはレンダリングしてくれるので、Vue単体だけでSSRしてなくてもちゃんとコンテンツ内容を理解してくれている模様。TwitterとかFacebookとかのSNSサービスのクローリングがこの先の未来にレンダリングしてくれるようになったらSSR不要論は高まってくるとは思う。

#### 今回Nuxt・Vueで使ったプラグイン紹介
どんなことが出来るのか紹介します。Nuxt・Vue周りは専用のプラグイン（頭にnuxtがついていたりvueがついていたりするやつ）が多いので本当にありがたいです。

##### 全般
- @nuxtjs/pwa：PWA設定が簡単にできる
- @nuxtjs/markdownit：マークダウン記述で書ける（主に利用規約とか書く時に使った）
- nuxt-buefy：NuxtでBuefyのテーマを使う
- vuexfire：Firestoreとのデータ連携ができる
- vuex-persistedstate：画面更新したときにもデータを残せるようになる
- cross-env：develop環境とproduction環境みたいに分けたい時

参考：
[Nuxt.jsとFirebaseでSPA×SSR×PWA×サーバーレスを実現する](https://inside.dmm.com/entry/2018/04/10/nuxt-firebase)
[Nuxt.jsとFirebaseを組み合わせて爆速でWebアプリケーションを構築する](https://qiita.com/potato4d/items/cfddeb8732fec63cb29c)
[nuxt.jsを使う時にlocalStorageでstoreを永続化する](https://qiita.com/sakapun/items/a0cf5698751ae70c8088)
[Nuxtでcross-envを使い環境ごとに環境変数を分ける](https://qiita.com/TakahiRoyte/items/c152ad8baa191ed1f8ae)

##### 画像作成周り
- emoji-mart-vue：絵文字のパレットを表示できる（ただしめっちゃ重い）
- vue-konva：Konva（後述）によるCanvas描画が簡単にできる
- fontfaceobserver：フォント読み込みチェックなどで使える

##### 投稿周り
- vue-social-sharing：SNSシェア系のボタンが簡単に作れる
- vue-clipboard2クリップボードコピーが簡単に出来る

##### Webサイト運営周り
- @nuxtjs/google-tag-manager：今どきAnalyticsタグはGoogleタグマネージャーで管理しよう
- @nuxtjs/sitemap：サイトマップ作りに必要
- vue-google-adsense：AdSenseタグを埋め込みが簡単

参考：
[もうmeta要素を迷わない！最低限入れるべきmeta要素のまとめ](https://qiita.com/pompom0c0/items/5c00a188aab744cfc918)
[nuxt.js(v2)でgenerate納品する前にやっておきたい設定](https://qiita.com/amishiro/items/11bd642728f6b5838189)

### Buefy（CSSフレームワークBulma in Vue）はいいぞ
[Bulma](https://bulma.io/)いいですよね。軽くてシンプルだけどイケてる。それをVue用にしたのが[Buefy](https://buefy.org/)です。Vueのおいしい書き方をしながらBulmaのフォームとかが使えるのですごく助かっています。

ちなみにスライダーとかはないので、使いたい場合は[Bulma-Extensions](https://wikiki.github.io/)というのがあるのでこれも便利。

### Konva（Canvas描画系ライブラリ）はいいぞ
いまどきCanvasだけでゴリゴリ書いている人なんて存在しているんでしょうか…？そう思ってしまうほど、[Konva](https://konvajs.github.io/)は一度使ったらやめられない便利ライブラリです。

Konvaなにそれって方は、[**今すぐKonvaのデモを見た**](https://konvajs.github.io/docs/sandbox/)方が良い。なんで今まで使っていなかったか悲しくなるくらい良い。そんなKonvaもVue用に最適化されたvue-konvaがあるのでそれを使いましょう。

ちなみにCanvasでStorageに上げた画像を使おうとした時に、Cross Originの影響でうまく使えないことがあったので、[Firebase StorageにCORSの設定をする](https://qiita.com/niusounds/items/383a780d46ee8551e98c)を参考に設定しました。

### Google Fontsはいいぞ
このアプリでは[Google Fonts](https://fonts.google.com/)からフォントを読み込んでいます。無料で使えるWebフォントで、表示環境依存のフォント表示を解消することができます。フォントはCDN配信なのでDLもわりと早めかとは思います。

自前でフォントを用意すると、帯域圧迫や通信量などでこの手の従量課金制のサーバーだとちょっとつらいかもというのは感じましたので今回は迷うこと無くGoogle Fontsに手を出しました。

ただフォントを読み込んでる最中の挙動とかそのあたりは若干面倒だった（ここでfontfaceobserverを駆使する感じ）ので、一長一短かもしれない。

## 技術トピック（TIPS・躓いた点など）
### Firebaseのルールの書き方：ユーザ毎の権限を付与＆リファレンス参照
FirebaseでFirestore・Storageへの書き込み権限を与えることで、かなり細かい制御が出来るようになります。

**読み込み権限は全員にもたせたい**けど、**書き込み（投稿作成・削除）は作った本人だけにしたい**、といった、SNS系あるあるの仕様の場合はちゃんとルールを作ってあげないとNGです。（javascript側の処理で出来るんじゃ…ていう考え方をする方もいらっしゃるかとは思いますが、基本的にユーザがいじることができる、クライアントサイドにこういう削除系の処理を書くとハックされる余地が残ります）

長くなってしまったので、こちらの記事にまとめています
[Firebaseのルールの書き方：ユーザ毎の権限を付与＆リファレンス参照](https://blog.f-arts.work/archives/1127)


### firebaseapp.comドメインを使用不可にしたいけどダメそう
調べてみたところ、firebaseapp.comのドメインを無かったことにして、全て独自ドメインにする術は今のところなさそう。

https://github.com/firebase/firebase-tools/issues/1072

ということでありきたりですが、愚直にJavascript側でリダイレクトする感じを常に読み込んでくれるような適当な箇所に書き足します。（layouts/default.vueとかのどっかに書くとか、もっといい場所はあるかも）

```js

    // もしfirebaseのURLだったらリダイレクトする
    if ("mojipic-production.firebaseapp.com" === window.location.hostname) {
      window.location.href = "https://mojipic.f-arts.work/"
    }
```

調べてて見つけたリファラなど考慮するリダイレクトも面白い。
[やはり、お前らのJavaScriptでのリダイレクト実装は間違っている](https://qiita.com//1987yama3/items/5ff58b6195fe6c3f268b)

ただ、今回のケースではfirebaseapp.comでアクセスされる想定はそもそも想定外ですので、普通のリダイレクトでいきました。firebase.ruleとかでrewrite設定とか出来ないかな…


### FirebaseのTwitterログインからアクセストークンを取得する
FIrebase認証して最初にリダイレクト時に取得出来る感じだったので、ログインチェック時にトークンを取得して、store（永続化済み）に入れることにしました。使いたいときにstoreから参照する感じです。

こんな感じ

``` js
credential = firebase.auth().getRedirectResult().then(function(result) {
  if (result.credential) {
    // credentialがあったときの処理
    // 例えばそのままreturnとか
    return result.credential
  }
}).catch(function(error) {
  // エラー処理
});
```

参考：[Google ログインと JavaScript を使用して認証する](https://firebase.google.com/docs/auth/web/google-signin?hl=ja)

ちなみに、こんな感じのデータが入ります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/262161/43ebabde-71d9-3d28-acfe-de51bc3c2253.png)

これでaccess_token_key・access_token_secretが手に入るので、あとはアプリ側のconsumer_keyとconsumer_secretをセットにしてあげれば画像投稿など何でも出来るようになります。

ちなみに、consumer_keyとconsumer_secretはフロント側に入れるとバレちゃって大変なので、Firebase Functionの方に記述しました。この辺は「Javascript Twitter API 投稿」とかで検索すると情報が山程出てくるので今回は割愛します。

### SSRしたいページ以外は静的ファイルで配信したい
今回挑戦したかったことの一つ。FIrebaseはFunctionによるレンダリングもキャッシュされるとのことなのである程度のスピードは出るようにはなりますが、他の方々も言う通りSSRはレンダリング処理をサーバー側で噛ませるため、ワンアクション遅くなります。（感覚的には、Webサイトにアクセスしたときに、真っ白画面がコンマ秒ですがあるな…という感じ。ちゃんとチューニングすればいい話ではありますが…）

そこで今回はFirebaseの設定をイジって、OGPを動的にしたいページのみをSSR配信することにしてみました。

- 投稿ページ（/p/****）：https://mojipic.f-arts.work/p/91loNya3pdgSO0ebEib4
- ユーザページ（/u/****）：https://mojipic.f-arts.work/u/HfhTLnCdzRRHyuvPN3P2039jO2t2

この2種類のページをSSR配信し、残りはNuxtのgenerateで生成したファイルでいきます。

まずは、```nuxt generate```コマンドで出来た```distディレクトリ```を```public```に配置します。また、SSR用に作ったディレクトリも```dist/functions```に配置します。

dist/functions配置のあたりは、先述の「[Nuxt.jsとFirebaseでSPA×SSR×PWA×サーバーレスを実現する](https://inside.dmm.com/entry/2018/04/10/nuxt-firebase)」とか「[Nuxt.jsとFirebaseを組み合わせて爆速でWebアプリケーションを構築する](https://qiita.com/potato4d/items/cfddeb8732fec63cb29c)」でやっているFunctionでNuxtを配信するやり方そのままです。唯一の違いはgenerateしたのを配置して、特定URLだけfunctionに処理を流すというやり方です。

firebase.jsonはこのように書いています。画像配信assets周りはgenerateのを共有で使える＆functionSSR側のassetsはdist/functionsの方に入ってるので、こんなシンプルな感じでも共存できました。

``` js:firebase.json
{
  "hosting": {
    "public": "public",
    "rewrites": [{
      "source": "/p/**",
      "function": "ssr"
    },{
      "source": "/u/**",
      "function": "ssr"
    }]
  },
  "functions": {
    "source": "dist/functions"
  }
}
```

大丈夫だとは思うのですが、function側で使われている```dist/client/```と、静的配信で使っている```dist/assets/```assetsファイルの差分無いよなとmd5sumを見てみましたが、今の所大丈夫そうでした。

ちなみにFunction処理用にに渡す```.nuxt```のディレクトリは```nuxt generate```で生成されたものを使っています。ここは割と怪しいところなので、強いひとの意見を知りたい。今の所変な影響は出てなさそうです。

``` bash
diff <(find .nuxt/dist/client/ -type f | xargs md5sum | cut -d " " -f 1) <(find dist/assets/ -type f | xargs md5sum | cut -d " " -f 1)
```

### 本番ではconsole.logの表示をしないようにする
nuxt.config.jsのbuild設定に書き足します。環境変数NODE_ENVがproductionの時にdrop_consoleするようにしました。

``` js
const TerserPlugin = require('terser-webpack-plugin')
const environment = process.env.NODE_ENV || 'development'

module.exports = {
  // ...中略...
  build: {
    // ...中略...

    optimization: {
      minimize: environment == 'production',
      minimizer: [
        new TerserPlugin({
          terserOptions: {
            compress: { drop_console: true }
          }
        })
      ]
    }
  }
}
```

### emoji-martが重いのと変な挙動が
emoji-mart重い…ので、デフォでは非表示にしてみた。

あと、emoji-mart-vueの最新バージョン起因かもですが、2.6.5にしたときに、画面遷移時に画面が微動だにしなくなって、数秒後に突然動くという、謎挙動（Webアプリとしては致命的）があったので、2.6.4にバージョンを少し落としました。最新バージョンではまだ確認してないですが、なんか変だなと思ったらバージョンを変えてみて下さい。

### konvaの文字配置は環境差分がありそう
konvaで文字の位置がズレる現象がある。Canvas事情かもですが、意外と辛いです。この例では、下のロゴの位置が結構ずれます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/262161/55f1b6d2-157f-b12c-bc28-25184cc11a4e.png)

verticalAlign設定のせいかなと、top・middle・bottomと色々試したのですがダメでした。もしご存知の方がいましたら救いの手を…

### プラグインが多くてページ読込が遅いのでつらい
プラグインの状況をnuxtのアナライズモードで見ることができます。
https://ja.nuxtjs.org/api/configuration-build#analyze

この通り書いたら、http://localhost:8888 で起動にならなかった（analyze: trueのデフォルトがなぜかserverではなくstaticになってる？）のでこんな感じで書き直し。

``` js
analyze: {
  analyzerMode: 'server',
  analyzerHost: '0.0.0.0',
  analyzerPort: '8888'
}
```

視覚化できてめっちゃいいですよね。

![webpack-bundle-analyzer](https://cloud.githubusercontent.com/assets/302213/20628702/93f72404-b338-11e6-92d4-9a365550a701.gif)
[webpack-bundle-analyzerより引用](https://github.com/webpack-contrib/webpack-bundle-analyzer)

私の環境では、「firebase.js」と「emoji-mart」が結構占めてた…消したくは無いしどうすればいいのか…今回は諦めましたｗ（emoji-martは別途非同期読み込みに回す感じがいいのかなとは思う）

#まとめ
FirebaseとNuxtを使うと、**結構ちゃんとした所までアプリが作れるんだなと驚き**ました。
Nuxtの場合は一度作っておけば、コンポーネント管理のメリットもあり、**他のアプリを作るときにも使いまわせたりできる**のですごく良いなと思いました。開発効率がめっちゃあがりますね。ぜひ皆さんも**FirebaseとNuxtで最高のコーディングライフ**をお過ごしください！

## 勉強するときのオススメ

### Vueドキュメント
公式ドキュメント侮ることなかれ、読みやすいです。ちゃんと日本語ですぞ。
https://jp.vuejs.org/v2/guide/

### Nuxtドキュメント
こちらの公式ドキュメントも読みやすい。日本語。
https://ja.nuxtjs.org/guide/

### Firebaseドキュメント
こちらの公式ドキュメントも読みやすい。ただ章立てから欲しい情報が若干見つけにくいときもある。日本語。
https://firebase.google.com/docs/?hl=ja

### 書籍：Vue.js&Nuxt.js超入門
掌田先生著。Vue・Nuxtに加えて外部API連携（Firebaseも少しある）も扱っているので、ガッと体系的に勉強したい時などに大変良い。
[<img src="https://qiita-image-store.s3.amazonaws.com/0/262161/3df9900f-8b19-631a-54ed-af673147e6d8.jpeg" alt="image" width="30%">](https://amzn.to/2Kfee0c)

## 終わりに

本記事をここまでお読みいただきありがとうございました。またダラダラ書いていたら長くなってしまいました。。。こんな書き方ありえねぇナメてんのかとかあると思うので、**是非**[**Twitter(@y_kawase)**](https://twitter.com/y_kawase)**で優しく絡んで**下さい。

**直接ビデオ通話で技術系相談したいぞ**という方は、[**こちら**](https://menta.work/plan/933)にも登録しておりますので、も良ければご活用下さい。答えられることなら何でも答えます。 → https://menta.work/plan/933


#### 過去記事・関連記事も宜しければどうぞ

- [Reactで誰もがやりたかった10の機能。アプリ構想はあるけど作れない人の壁をぶっ壊す。](https://qiita.com/y_kawase/items/8f1b5a303400a09c4923)
- [Firebaseで完結するリッチなWebアプリ構築の勘所](https://qiita.com/y_kawase/items/1de690b40553ef76acb3)
- [Qiita初投稿でも狙ってバズらせられた話『5つの成功と2つの失敗』](https://blog.f-arts.work/archives/857)

ゆるいネタで**noteも始めてみた**ので、もし興味があればこちらもご覧いただけると嬉しいです。

- [お前はThunderbolt3を何も知らない。USB Type-Cに翻弄されないための教養。](https://note.mu/ykawase/n/n23deaa2a0ef2)