Firebaseは2014年10月にGoogleに買収されたことで一躍有名になったBaaS(Backend as a Service)です。本記事ではちょっとしたリアルタイムウェブアプリケーションを作りながらFirebaseの機能を紹介します。
Firebaseとは
Firebaseはデータストレージ、ユーザー管理などアプリケーションのバックエンドとして必要となる機能をサービスを提供することで、アプリケーション開発者がクライアントサイドの開発に集中できるようにしてくれるBaaS(Backend as a Service)の一種です。
2014年10月にGoogleに買収され、Google Cloud Platform(GCP)の一員となりました。この買収によりGCPにはPaaS(Platform as a Service)としてGoogle App Engine、IaaS(Infrastracture as a Service)としてGoogle Compute Engine、BaaSとしてFirebaseと、いわゆるXaaS系が一通り揃ったことになります。
Firebaseの特徴
Firebaseはもともとは開発者用APIを持つウェブサイトに埋め込み可能なリアルタイムチャットサービスとして始まりました。
しかし、多くのユーザーがチャットサービスとしてではなく、ゲームなどのアプリケーションでリアルタイムにデータを同期するために使用したため、創業者たちはチャットサービスのリアルタイムメッセージングシステムを切り出して別サービスとしました。これが現在のFirebaseの元となっています。
そのため、Firebaseは数あるBaasの中でも特にチャットアプリのようなリアルタイムにデータを同期する必要があるサービスに適しています。
Firebaseの機能
リアルタイムデータベース
FirebaseのデータベースはスキーマレスないわゆるNoSQLで、特定のアプリケーションに関係するデータ全体がひとつのJSONオブジェクトとして保持される点が大きな特徴です。
これによりデータが階層構造をなすため、それぞれのデータが一意のURLを持つことができます。例えばデータベース全体を指すURLは以下のようになります。
- https://アプリケーションID.firebaseio.com
特定のデータを示すURLは以下のようになります。
- https://アプリケーションID.firebaseio.com/プロパティのパス
例えばアプリケーション名 my-first-chat-app のデータ全体が以下の様であるとして
{ "messages" : { "-K5kPGFquoTbqHYQqBRS" : { "body" : "message", "name" : "name" }, "-K5kPUqfBfdj4bAa1fyv" : { "body" : "message2", "name" : "name2" }, "-K5kR-lwtG4I5w9T36Xq" : { "body" : "message3", "name" : "name3" } }
最初のメッセージ(messages/-K5kPGFquoTbqHYQqBRS)の内容だけを確認したいのであれば、次のURLをブラウザで表示すればいいということになります。
- https://my-first-chat-app.firebaseio.com/messages/-K5kPGFquoTbqHYQqBRS
認証
Firebaseを使用すると非常に簡単にユーザー認証をアプリケーションに組み込むことができます。組み込みの認証機構としては、メールアドレスとパスワードを使用した認証、OAuthを使用した認証(Facebook, Twitter, GitHub, Google)、匿名ログインがあり、加えてJSON Web Tokens (JWTs)を使用して既存の任意の認証システムと連携することも容易です。
ホスティング
HTML、CSS、JS、画像などの静的なアセットは、Firebaseコマンドラインツールを使用して自身のドメイン上(アプリケーションID.firebaseapp.com
)、もしくは有料プランであれば独自ドメイン上に簡単にデプロイすることができます。
さらにデプロイの履歴は管理画面で見ることができ、問題があった場合には以前のバージョンにロールバックすることも可能です。
コマンドラインツール
Firebaseのホスティングサービスを利用するにはFirebaseコマンドラインツールを使用する必要があります。node.jsとnpmがインストールされていればコマンドツールは以下のコマンドで簡単にインストールできます。
$ npm install -g firebase-tools
firebaseコマンドで利用可能なサブコマンドは、以下のとおりです。
- firebase init
- プロジェクトディレクトリを初期化します。ホスティングサービスに必要なすべての設定は当コマンドによりプロジェクトディレクトリルートに作成されるfirebase.jsonファイルに含まれます
- firebase deploy
- 現在のプロジェクトをサーバーにデプロイします
- firebase disable:hosting
- ホスティングを無効にし、アクセスに対し”Site Not Found”ページを表示するようにします
- firebase login
- コマンドラインツールをログインします
- firebase logout
- コマンドラインツールをログアウトします
- firebase list
- 現在ログイン中のユーザーが利用可能なFirebaseアプリの一覧を表示します
APIとSDK
FirebaseデータベースにはREST APIがあり、さらにそのAPIを利用する各種環境用のクライアントライブラリが標準で用意されています。
なお、これらの標準クライアントライブラリを使用するとFirebaseはオフラインでの動作が保証されます。つまりネットワーク接続がない場合でも、Firebaseデータベースの読み書きの対象を一旦ローカルのキャッシュとすることで、アプリケーションは正常に動作します。その後、接続が復活した時に内容がサーバーと同期されます。
また、標準ライブラリに加えて、REST APIを使用する非公式なライブラリとして以下の様なものもあります。これ以外にもいろいろとありますので、サーバーサイドで自分の好きな言語を利用したい場合はGitHubなどで検索してみるといいでしょう。
- Python-Firebase(Python)
- Firebase-Php(PHP)
- Firebase-Ruby(Ruby)
- BigBertha(Ruby)
- Rest-Firebase(Ruby)
なお、標準クライアントライブラリを使用した場合はオフラインでの動作が保証されますが、非公式ライブラリを使用した場合はその限りではありません。
サンプルアプリケーション
Firebaseを使用した基本的なアプリケーション開発の流れを確認するために簡単なチャットアプリケーションを作成してみましょう。先に紹介したとおりFirebaseクライアントライブラリは環境に応じて複数ありますが、今回はJavaScript版クライアントライブラリを使用してWebアプリケーションを作成します。
Firebaseアプリケーション作成
まずはじめに、今回のサンプルから使用するデータベースを用意するため、ウェブコンソールからFirebaseアプリケーションを作成します。http://firebase.com を開き、画面右上のログインボタンをクリックしてログインしてください。
アカウントを新たに作成しても構いませんし、GoogleアカウントやGitHubアカウントを使用してログインすることもできます。
ログイン後、左下の入力エリアにアプリ名とアプリURLを入力して、アプリを作成します。今回は以下の様な設定を使用するものとします。
App Name | My First Chat App |
---|---|
App URL | https://my-first-chat-app.firebaseio.com |
サーバーサイドで行う作業は以上です。これだけでNoSQLデータベースが作成され、クライアントアプリから自由に利用できるようになりました。
サンプルアプリケーションの初期化
サンプルアプリケーションは最終的にFirebaseホスティングサービスを利用するため、まずfirebase initコマンドを実行してプロジェクトディレクトリを初期化します。
% firebase init? What Firebase do you want to use? my-first-chat-app ? What directory should be the public root? public ✔ Public directory public has been created Firebase initialized, configuration written to firebase.json
初期化にあたって
- アプリ名
- デプロイするファイルを配置するディレクトリ
を聞かれるので、アプリ名は先程作成したものを、ディレクトリ名はデフォルトのpublicを設定してください。
ウェブアプリケーション作成
それではここから実際に冒頭のサンプルアプリケーションを作成していくこととします。といっても必要となるのはHTMLファイルが一つだけ、それも非常に小さなものですので先に全体を見てしまいましょう。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8" /> <title>Firebaseサンプル1</title> </head> <body> <div> <input id="name" placeholder="名前" /> <input id="message" placeholder="メッセージ" /> <button id="send">投稿</button> </div> <ul id="messages"> </ul><script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-alpha1/jquery.min.js"></script> <script src="https://cdn.firebase.com/js/client/2.3.2/firebase.js"></script> <script> // データベースの参照を準備 var firebaseRef = new Firebase("https://my-first-chat-app.firebaseio.com"); // ... 1 var messagesRef = firebaseRef.child('messages'); // ... 2 // 既存メッセージを表示 messagesRef.on('child_added', function(snapshot) { // ... 3 var msg = snapshot.val(); $('<li>').text(msg.name + ': ' + msg.body).prependTo('#messages'); }); $('#send').click(function() { // 新規メッセージを投稿 messagesRef.push({ // ... 4 name: $('#name').val(), body: $('#message').val() }); }); </script>
</body> </html>
今回のサンプルアプリケーションのコードはこれだけ、コメントや空行を除けばJavaScript部分はたったの12行です。このコードをローカルに保存し、ブラウザで開いてみてください。HTMLを含めて全体でも40行弱のコードですが、複数ブラウザで開いて、一方でメッセージを入力すればその内容はリアルタイムに他方に反映され、(かろうじて)チャットとして利用できます。
コードの詳細については次回以降に譲りますが、簡単に説明すると、行われている処理は以下のとおりです。
- アプリケーションURLを引数としてFirebaseオブジェクトをインスタンス化し、前節で作成したFirebaseデータベースに接続するためのオブジェクトを生成します。
- Firebaseデータベースのmessagesオブジェクトへの参照を取得します。この参照への操作はサーバー上のFirebaseデータベースに保存されることになります。
- messagesオブジェクトに子ノードが追加された場合のコールバック関数を登録します。今回はコールバック関数内でメッセージの内容をli要素としてul要素に追加しています。なお、onメソッドで登録されたコールバック関数はHTMLの初回読み込み時にも実行されるため、初回読み込み時用の処理を特別に記述する必要はありません。
- messagesオブジェクトに子ノードを追加します。
オフライン対応の確認
さて、ここで一つ面白い実験をしてみましょう。複数のブラウザでサンプルアプリを開き、使用しているコンピューターのネットワークをOFFにしてください。
そのまま一方の画面でメッセージをいくつか入力すると、メッセージを入力した画面では新しいメッセージがリストに追加されますが、他方の画面にはメッセージが追加されません。
その状態でコンピューターのネットワークをONにするとどうでしょう。少し経って他方の画面にもメッセージが表示されるのが確認できるはずです。
実はFirebaseデータベースの読み書きはいったんローカルDBを経由して行われています。そのためネットワーク接続が不通の場合もローカル側の処理は正常に完了し、ネットワークが回復すると自動的にデータがサーバーと同期されるのです。
これによりアプリケーション開発者はネットワークの状態を一切意識することなくリアルタイムアプリケーションを作成することができます。
リアルタイムに状態を同期する必要がある場合、この機能だけでもFirebaseを採用する価値があるのではないかと私は思うのですが、みなさんはいかがでしょうか?
データベースの内容確認
サンプルアプリにメッセージをいくつか書き込んだらダッシュボードでデータベースがどうなっているか、内容を確認してみましょう。https://アプリケーションID.firebaseio.com/ にアクセスしてみてください。
ちゃんと登録されています。
ちなみにこのダッシュボードから値を変更することもでき、その場合ももちろんクライアント側のイベントハンドラが発火され、ブラウザ側の表示はリアルタイムに変更されます。
デプロイ
最後に、今回のアプリケーションをFirebaseにデプロイして実際に利用できるようにします。firebase initコマンドを実行したディレクトリでfirebase deployコマンドを実行してください。
% firebase deploy=== Deploying to 'my-first-chat-app'...
i deploying hosting i preparing public directory for upload... ✔ 1 files uploaded successfully
✔ Deploy complete!
URL: https://my-first-chat-app.firebaseapp.com Dashboard: https://my-first-chat-app.firebaseio.com
Visit the URL above or run firebase open
では、ブラウザで https://my-first-chat-app.firebaseapp.com を開いてみましょう。開発時と同じデータベースを参照しているので先ほど入力したメッセージがここでも表示されています。
ちなみにアプリのドメインは firebaseapp.com で、ダッシュボードのドメインは firebaseio.com です。うっかり打ち間違えないように気をつけましょう。
まとめ
いかがでしょう。Firebaseを使用すれば非常に簡単にリアルタイムアプリケーションが作成できるということが分かっていただけたのではないでしょうか。
今回はFirebaseの全体的な機能の概要を説明しました。次回はもう少し複雑なアプリケーションを作りながら、Firebaseのそれぞれの機能をより詳細に掘り下げていきたいと思います。お楽しみに。