2019/02/17
まだサーバーで消耗してるの?Firebase(サーバーレス)とNuxt.js(Vue系)ならWebアプリ運営は最強でしょ!?
この記事は、
という人向けに、「こんな感じで構築すれば効率良く開発できそうよ」というのを、勉強になった記事や技術的トピック・躓いた点なども合わせて紹介させていただきます。初心者向け&技術トピック気になる方向けです!
Moji → Picは、文字だけだとなかなか目につく投稿ができないなぁ…とお困りの時にインパクトある画像が即座に出来るアプリ。目立ったツイートで友達に差をつけろ!
そんな感じで、他人の金で肉や寿司が食べたいときにでも使ってみて下さい。無為なツイートがもっと無為になることでしょう。
ログインしなくても画像作ったりDL出来たり楽しめるので、是非遊んでくださいませ。
GIGAZINEでも紹介いただきました!!サービスについて私よりわかりやすくまとめていただいたので、こちらも是非御覧ください。
基本技術トピック:FirebaseとNuxtが凄いところ
応用技術トピック:このアプリの工夫ポイント
残念トピック:改善したいポイント
このあたりの内容を入れてお送り致します。
このアプリ制作では、オレオレルールですが、「5秒でログイン、30秒で投稿」を肝に銘じ作りました。UXデザインに通じているわけではないので虚言甚だしいですが、どんなに良いアプリでも「導線が上手く出来てないアプリは死ぬ」「機能の詰めすぎ悲しいかなエンジニアのエゴ」などを常に意識しながら最近は生きています。ちなみにこのアプリがそれを体現できているかは実際に見に行って見て下さい(石は投げないで下さい)。
そういう意味では、Firebaseを使って構築ってなると、Firebaseの機能をそのままサクっと使いたいので、ミニマルでシンプル構成に引っ張られやすいのも、私はメリットだと感じています。(もちろん複雑なアプリも出来る…!)
モノづくりをしたりプログラミング先生をやったり。最近は、Railsで歌声専門フリマサイトとか、React勉強で今期アニメ検索アプリ(Qiita記事)とか作ったりしました。
また、Web系言語やらのネタでブログにTIPSをたとめていたり、Twitter(@y_kawase)でもちょこちょこ真面目ネタも呟いているので宜しければ絡んで下さい。
直接ビデオ通話で技術系相談したいぞという方は、こちらにも登録しておりますので、も良ければご活用下さい。答えられることなら何でも答えます。 → https://menta.work/plan/933
前半はわりと基本的な内容や紹介なので、技術的な内容で気になる方は後半をご覧下さい。
私自身も勉強中の身ですので不備不足はご容赦下さい。情強の方のアドバイス・ご指摘など大歓迎です…!
最近すごく感じるのが、小規模開発(個人開発含む)や趣味の場合、サーバーコストがサービス継続に影響しているという所です。
せっかく作ったし、いつかバズるんじゃねと思ってサービスを動かし続けてても、サーバーの維持費に月500円(年間6000円)かかるわけです。数年後アクセス解析をみて殆どアクセスなんてなかったんや…と途方に暮れながらサービスクローズする姿が私には見えます…(本当にあった怖い話)
そんなこともあり、最近は
という、Nuxt.js(Vue.js)+Firebaseが今一番身につけて損は無い技術なんじゃないかと思った次第です。特に、このセットの記事は最近良く見かけることもありますので、FirebaseとNuxtの2人なら最強!ってことだと思ってます。
鋭い方は覚えているかもしれませんが、以前私はVue系ではなく、React使ってました。いつの間にVue系に鞍替えしたのよという感じ。そうです、Reactで誰もがやりたかった10の機能。アプリ構想はあるけど作れない人の壁をぶっ壊す。という記事を書いたりして勉強していたのですが、その後いざSSR(サーバーサイドレンダリング)をしたくなってNext.jsに手を出しました…ただ悲しいかな私には難しすぎました…(特にstoreやthemeまわりの設定がしんどかった…)
ふと、Nuxt.jsを触ってみることにしたところ、便利プラグインやら簡単な設定やらで、初心者にとっては大変ありがたい仕組みが用意してくれていました。後ほど技術要素のお話でも取り上げようと思いますが、「store管理がデフォで入ってる」「Buefyテーマ(CSSフレームワーク)を読み込んでくれるプラグイン」とかがNuxt用に最適化し用意されていて、使いたいものを設定ファイルに書けばすぐに動きました…Nuxtさん優しすぎる…
もちろん最終的にはそれぞれのフレームワークには確固たる方針があってメリットがあると思います。React・Vue・Angularが今のところは3大JSフレームワークと言われていて、それぞれメリットがあります。それぞれ素晴らしい特色があるのできちんとどれが良さそうか見定めると良いと思います!!
参考になりそう→【JavaScript】3大フレームワーク Angular, React, Vue.jsを比べてみよう
個人的な意見として、初心者がとりあえずサクッと構築したいという場合は、Vue.js/Nuxt.jsの方が日本語情報も多いですしとっつきやすそうだなという感想です。GitHubのStar数はVue>Reactになったし、ひとまずはVue系の時代がまだ続くでしょと思う。
あとは、Nuxt界隈では@potato4dという神が君臨しており、Vue・Nuxtまわりのお話をよくアウトプットしてくれるので、それも凄く心強いなと思っています。
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×サーバーレスを実現する
Nuxt.jsとFirebaseを組み合わせて爆速でWebアプリケーションを構築する
TypeScriptで書くのもいいよね。私は今回は断念したけど。。
TypeScript + Nuxt.js + Firebase (+ SSR)でWebアプリを構築
文字通りサーバーが無く、自分でサーバーを借りたり立ち上げたりする必要が無いということ。サーバーが常に待機状態にある従来と違い、アクセスされた瞬間に処理が走りアクセスが無い時はお休みをしているイメージです。
AmazonのAWSならLambdaなどがサーバーレス系で強かったイメージですが、最近はFirebaseがかなりグイグイ来ていますね。
普通のサーバー有りのものと違い、制約は多いですが(動かせる言語に限りがある、バージョンが指定されている等)、常時サーバーを動かさなくて済むため、コストが大幅にカット出来ます。
また、サーバーの場合は規模を大きくする際に、構成を増やしたり、その分通信経路を振り分けたり…とスケールアップが大変な部分がありますが、サーバーレス系の場合はこのあたりのスケールアップを勝手にやってくれる(1アクセスにつき1処理なので、アクセスが増えたら処理要員を増やせばいいだけ)ので、インフラ系で悩むことから開放されます。
FirebaseはBaaSと言って、アプリケーションのバックエンドのサービスになります。サーバーレスの機構を使いやすくするために、
など、とても便利な付随機能があります。
もちろん認証系に特化したサービスAuth0を使うとかも良いかとは思いますが、Firebaseですべてを完結できるので使わない手はないでしょう。
そうなんです、お値段なんと無料です。すごい。 外部との通信などの場合はプランを有料プラン(Blazeプランという従量制プラン)に変更する必要はありますが、ご安心。毎月の無料枠がかならずついているので、たいていの人は無料枠内に収まるのかとは思います。
なお、無料枠内は、Function呼び出しが12.5万回/月や、HostingのTransferが10GB/月とかなので、これを超えるサービスはもう無料枠の必要ないでしょという感じがあります。Firebaseのお値段・プランなどは公式サイトで確認するといいです。
つまりサービス開始時はおそらくたいていはほとんど料金を払う必要が無く、ゆくゆくサービスが大規模化していった場合にようやくお金を払う、そんなシステムになっています。
バズってアクセスが集中した月だけお金を払うようなシステムなので、普段は音沙汰ないけど、突然有名人にRTされてアクセス集中してサーバーが落ちたなんてことはありません。これも小規模・個人開発ではありがたい点なのかなと思います。
先述の通りNuxtは色々なプラグインが豊富に用意されており、初心者にとっては大変使いやすい仕組みができています。またNuxtのベースになっているVueも初心者受けが良いと好評なツールですので、「とりあえずNuxt&Vue」で作ってみるのは良いんじゃないかなと思います。
ディレクトリ構成とかも既に決まっていたりするので、そういった制約が逆に構築しやすくなったりしたりします。
そもそもVue.jsって何って人はこのあたりを読んでおけばおk
jQuery から Vue.js へのステップアップ
簡単に言うと、JavascriptとHTML表示側の連携をすごくやりやすくしてくれているツール。入力が発生するアプリを作らないと実感わかないと思うのですが、純jsやjQueryで入力フォーム沢山&フォーム入力イベント処理ありのアプリを作ると管理出来ない代物がもれなく出来るので死にます(私だ)。
Vueの公式ドキュメントがしっかりしているので、とっつきやすいです。日本語ドキュメントもあります(ちょっと最新バージョンには対応が遅いけど)
ちなみに、最近はTypescriptでVueを書くのも流行っているので気になる方はチェックしてみては如何でしょうか。vue.js + typescript = vue.ts ことはじめ
ただ、Vueはクライアント側でレンダリングをするため、よく言われている話ですが、TwitterなどSNSでシェアした時に、投稿ページ毎のOGP画像などが反映されません(これはTwitter等では、レンダリングする前のデータを読み込んでいたりするため)。そこで、SSRという技術が必要になり、Nuxtが活躍したりします。
そういう意味では、SNSでのシェア時、個別ページ毎にOGP設定とかタイトル設定とかしなくて良いよという方は、Nuxt使わずにVueだけでも良いと思います。
サーバーサイドレンダリングするための設定がすでにされているのでめっちゃ便利です。
Nuxtの公式ドキュメントもしっかりしているので大変分かりやすい。
ちなみに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.jsとFirebaseでSPA×SSR×PWA×サーバーレスを実現する
Nuxt.jsとFirebaseを組み合わせて爆速でWebアプリケーションを構築する
nuxt.jsを使う時にlocalStorageでstoreを永続化する
Nuxtでcross-envを使い環境ごとに環境変数を分ける
参考:
もうmeta要素を迷わない!最低限入れるべきmeta要素のまとめ
nuxt.js(v2)でgenerate納品する前にやっておきたい設定
Bulmaいいですよね。軽くてシンプルだけどイケてる。それをVue用にしたのがBuefyです。Vueのおいしい書き方をしながらBulmaのフォームとかが使えるのですごく助かっています。
ちなみにスライダーとかはないので、使いたい場合はBulma-Extensionsというのがあるのでこれも便利。
いまどきCanvasだけでゴリゴリ書いている人なんて存在しているんでしょうか…?そう思ってしまうほど、Konvaは一度使ったらやめられない便利ライブラリです。
Konvaなにそれって方は、今すぐKonvaのデモを見た方が良い。なんで今まで使っていなかったか悲しくなるくらい良い。そんなKonvaもVue用に最適化されたvue-konvaがあるのでそれを使いましょう。
ちなみにCanvasでStorageに上げた画像を使おうとした時に、Cross Originの影響でうまく使えないことがあったので、Firebase StorageにCORSの設定をするを参考に設定しました。
このアプリではGoogle Fontsからフォントを読み込んでいます。無料で使えるWebフォントで、表示環境依存のフォント表示を解消することができます。フォントはCDN配信なのでDLもわりと早めかとは思います。
自前でフォントを用意すると、帯域圧迫や通信量などでこの手の従量課金制のサーバーだとちょっとつらいかもというのは感じましたので今回は迷うこと無くGoogle Fontsに手を出しました。
ただフォントを読み込んでる最中の挙動とかそのあたりは若干面倒だった(ここでfontfaceobserverを駆使する感じ)ので、一長一短かもしれない。
FirebaseでFirestore・Storageへの書き込み権限を与えることで、かなり細かい制御が出来るようになります。
読み込み権限は全員にもたせたいけど、書き込み(投稿作成・削除)は作った本人だけにしたい、といった、SNS系あるあるの仕様の場合はちゃんとルールを作ってあげないとNGです。(javascript側の処理で出来るんじゃ…ていう考え方をする方もいらっしゃるかとは思いますが、基本的にユーザがいじることができる、クライアントサイドにこういう削除系の処理を書くとハックされる余地が残ります)
長くなってしまったので、こちらの記事にまとめています
Firebaseのルールの書き方:ユーザ毎の権限を付与&リファレンス参照
調べてみたところ、firebaseapp.comのドメインを無かったことにして、全て独自ドメインにする術は今のところなさそう。
https://github.com/firebase/firebase-tools/issues/1072
ということでありきたりですが、愚直にJavascript側でリダイレクトする感じを常に読み込んでくれるような適当な箇所に書き足します。(layouts/default.vueとかのどっかに書くとか、もっといい場所はあるかも)
// もしfirebaseのURLだったらリダイレクトする
if ("mojipic-production.firebaseapp.com" === window.location.hostname) {
window.location.href = "https://mojipic.f-arts.work/"
}
調べてて見つけたリファラなど考慮するリダイレクトも面白い。
やはり、お前らのJavaScriptでのリダイレクト実装は間違っている
ただ、今回のケースではfirebaseapp.comでアクセスされる想定はそもそも想定外ですので、普通のリダイレクトでいきました。firebase.ruleとかでrewrite設定とか出来ないかな…
FIrebase認証して最初にリダイレクト時に取得出来る感じだったので、ログインチェック時にトークンを取得して、store(永続化済み)に入れることにしました。使いたいときにstoreから参照する感じです。
こんな感じ
credential = firebase.auth().getRedirectResult().then(function(result) {
if (result.credential) {
// credentialがあったときの処理
// 例えばそのままreturnとか
return result.credential
}
}).catch(function(error) {
// エラー処理
});
参考:Google ログインと JavaScript を使用して認証する
ちなみに、こんな感じのデータが入ります。これでaccess_token_key・access_token_secretが手に入るので、あとはアプリ側のconsumer_keyとconsumer_secretをセットにしてあげれば画像投稿など何でも出来るようになります。
ちなみに、consumer_keyとconsumer_secretはフロント側に入れるとバレちゃって大変なので、Firebase Functionの方に記述しました。この辺は「Javascript Twitter API 投稿」とかで検索すると情報が山程出てくるので今回は割愛します。
今回挑戦したかったことの一つ。FIrebaseはFunctionによるレンダリングもキャッシュされるとのことなのである程度のスピードは出るようにはなりますが、他の方々も言う通りSSRはレンダリング処理をサーバー側で噛ませるため、ワンアクション遅くなります。(感覚的には、Webサイトにアクセスしたときに、真っ白画面がコンマ秒ですがあるな…という感じ。ちゃんとチューニングすればいい話ではありますが…)
そこで今回はFirebaseの設定をイジって、OGPを動的にしたいページのみをSSR配信することにしてみました。
この2種類のページをSSR配信し、残りはNuxtのgenerateで生成したファイルでいきます。
まずは、nuxt generate
コマンドで出来たdistディレクトリ
をpublic
に配置します。また、SSR用に作ったディレクトリもdist/functions
に配置します。
dist/functions配置のあたりは、先述の「Nuxt.jsとFirebaseでSPA×SSR×PWA×サーバーレスを実現する」とか「Nuxt.jsとFirebaseを組み合わせて爆速でWebアプリケーションを構築する」でやっているFunctionでNuxtを配信するやり方そのままです。唯一の違いはgenerateしたのを配置して、特定URLだけfunctionに処理を流すというやり方です。
firebase.jsonはこのように書いています。画像配信assets周りはgenerateのを共有で使える&functionSSR側のassetsはdist/functionsの方に入ってるので、こんなシンプルな感じでも共存できました。
{
"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
で生成されたものを使っています。ここは割と怪しいところなので、強いひとの意見を知りたい。今の所変な影響は出てなさそうです。
diff <(find .nuxt/dist/client/ -type f | xargs md5sum | cut -d " " -f 1) <(find dist/assets/ -type f | xargs md5sum | cut -d " " -f 1)
nuxt.config.jsのbuild設定に書き足します。環境変数NODE_ENVがproductionの時にdrop_consoleするようにしました。
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-vueの最新バージョン起因かもですが、2.6.5にしたときに、画面遷移時に画面が微動だにしなくなって、数秒後に突然動くという、謎挙動(Webアプリとしては致命的)があったので、2.6.4にバージョンを少し落としました。最新バージョンではまだ確認してないですが、なんか変だなと思ったらバージョンを変えてみて下さい。
konvaで文字の位置がズレる現象がある。Canvas事情かもですが、意外と辛いです。この例では、下のロゴの位置が結構ずれます。
verticalAlign設定のせいかなと、top・middle・bottomと色々試したのですがダメでした。もしご存知の方がいましたら救いの手を…
プラグインの状況をnuxtのアナライズモードで見ることができます。
https://ja.nuxtjs.org/api/configuration-build#analyze
この通り書いたら、http://localhost:8888 で起動にならなかった(analyze: trueのデフォルトがなぜかserverではなくstaticになってる?)のでこんな感じで書き直し。
analyze: {
analyzerMode: 'server',
analyzerHost: '0.0.0.0',
analyzerPort: '8888'
}
視覚化できてめっちゃいいですよね。
私の環境では、「firebase.js」と「emoji-mart」が結構占めてた…消したくは無いしどうすればいいのか…今回は諦めましたw(emoji-martは別途非同期読み込みに回す感じがいいのかなとは思う)
FirebaseとNuxtを使うと、結構ちゃんとした所までアプリが作れるんだなと驚きました。
Nuxtの場合は一度作っておけば、コンポーネント管理のメリットもあり、他のアプリを作るときにも使いまわせたりできるのですごく良いなと思いました。開発効率がめっちゃあがりますね。ぜひ皆さんもFirebaseとNuxtで最高のコーディングライフをお過ごしください!
公式ドキュメント侮ることなかれ、読みやすいです。ちゃんと日本語ですぞ。
https://jp.vuejs.org/v2/guide/
こちらの公式ドキュメントも読みやすい。日本語。
https://ja.nuxtjs.org/guide/
こちらの公式ドキュメントも読みやすい。ただ章立てから欲しい情報が若干見つけにくいときもある。日本語。
https://firebase.google.com/docs/?hl=ja
本記事をここまでお読みいただきありがとうございました。またダラダラ書いていたら長くなってしまいました。。。こんな書き方ありえねぇナメてんのかとかあると思うので、是非Twitter(@y_kawase)で優しく絡んで下さい。
直接ビデオ通話で技術系相談したいぞという方は、こちらにも登録しておりますので、も良ければご活用下さい。答えられることなら何でも答えます。 → https://menta.work/plan/933
ゆるいネタでnoteも始めてみたので、もし興味があればこちらもご覧いただけると嬉しいです。