UUUM攻殻機動隊(エンジニアブログ)

UUUMのエンジニアによる技術ブログです

Angularfire2でつくるリアルタイムWEBアプリ

こんにちは、エンジニアのタナカです。

本日の社内勉強会ではFirebaseクライアントライブラリのAngularfire2を紹介させていただきました。
一昨年にGoogleに買収されて有名になったmBaasのFirebaseですが、社内でも意外と使ったことが無い人が多いようです。 無料でも利用できるので、個人での開発にもピッタリだと思います!

無料で利用できる範囲は以下のとおりですが、結構太っ腹な設定だと思います。

f:id:tnuuu:20160801112513p:plain

https://firebase.google.com/pricing/

リアルタイムWEBアプリについて

チャットアプリのSlackが有名なので皆さんご存知だと思いますが、以下の特徴があります。

  • 複数クライアント間でリアルタイムに同期が取られる
  • 同期にはWebSocketやLong pollingが使われる
  • サーバーにはnode.js、ライブラリにはsocket.ioが使われることが多い

Angularfire2とは?

Angularfire2は、Angular2用のFirebaseクライアントです。RxJSを使ってクライアントとFirebase間の同期を行うのが特徴です。

つくりかた

事前準備

プロジェクトの作成方法は、以下の公式ドキュメントに詳しく書いてあります。

https://github.com/angular/angularfire2/blob/master/docs/1-install-and-setup.md

この手順を一通り実施するとAngular2にAngularfire2を組み込んだプロジェクトのベースが作成されます。 srcディレクトリは以下の構成になり、アプリ作成の際はこのあたりに手を加えていくことになります。

f:id:tnuuu:20160801114620p:plain

今回はサンプルとしてSVGを使ったリアルタイム同期のお絵かきアプリを作成してみたいと思います。

テンプレートの編集

src/app/app.component.htmlを以下に変更します。

<svg x="0px" y="0px" width="1000px" height="1000px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000">
  <g *ngFor="let item of items | async">
    <path *ngIf="item.path" [attr.d]="item.path" stroke="blue" stroke-width="2" fill="none" />
  </g>
</svg>

内容を簡単に説明すると、itemsというリストに格納されるSVGのPATH情報をループで出力するというものです。

コンポーネントファイルの編集

src/app/app.component.tsを以下に変更します。

import { Component, HostListener } from '@angular/core';
import { AngularFire, FirebaseListObservable } from 'angularfire2';

@Component({
  moduleId: module.id,
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css']
})
export class AppComponent {
  title = 'app works!';
  items: FirebaseListObservable<any[]>;
  path: string;
  key: string = null;

  constructor(af: AngularFire) {
    this.items = af.database.list('items');
  }
  @HostListener('mousedown', ['$event'])
  onMousedown(event) {
    this.path = 'M ' + event.x + ' ' + event.y;
    this.items.push({path: this.path})
  .then((ref) => {
    this.key = ref['key'];
    }, function(error) {
      console.log("Error:", error);
    });
  }

  @HostListener('mousemove', ['$event'])
  onMousemove(event) {
    if (this.key == null) {
      return;
    }

    this.path += ' L ' + event.x + ' ' + event.y;
    this.items.update(this.key, {path: this.path});
  }

  @HostListener('mouseup', ['$event'])
  onMouseup(event) {
    this.key = null;
  }
}

こちらがサンプルアプリのメインプログラムとなるのですが、処理の流れは以下になります。

  1. mousedownのタイミングでSVGのPATHを生成、itemsにpushする
  2. mousemoveでPATHのLineToを追加し、itemsをupdateする
  3. mouupでPATHの生成を完了する

たったこれだけの処理で、firebaseサーバーへデータが送信され、各クライアントへの同期処理も行われます。

@HostListnerの書き方が見慣れないと思いますが、@はTypeScriptのDecoratorsの書き方で、@HostListnerはAngular2で定義されたDecoratorになります。

Angular2のDecoratorsについては以下のサイトが参考になります。

Angular 2で紐解くDecorators

デプロイ

firebaseならホスティングも無料で利用できます。デプロイもプロジェクトディレクトリ内で以下のコマンドを実行するだけです。
デプロイが完了すると、アプリケーションのURLが表示されます。

$ nam install -g firebase-tools
$ firebase init
$ firebase deploy

=== Deploying to 'angularfire2-test-d02d0'...

i  deploying database, hosting
✔  database: rules ready to deploy.
i  hosting: preparing dist directory for upload...
✔  hosting: 2476 files uploaded successfully
i  starting release process (may take several minutes)...

✔  Deploy complete!

Hosting Site: https://angularfire2-test-d02d0.firebaseapp.com
Dashboard: https://console.firebase.google.com/project/angularfire2-test-d02d0/overview

Visit the URL above or run firebase open

完成したサンプルアプリ

ブラウザを2つ立ち上げて、片方で落書きをしてみてください。もう片方もリアルタイムで同期されます。 (サンプルなのでバグ多いです。)

https://angularfire2-test-d02d0.firebaseapp.com/

ちなみにchromeのデベロッパーツールを開き、networkタブ→WSタブの一覧に表示される「.ws?〜」のセッションを選択、framesタグを選択するとWebSocketにて送信されたデータが確認できます。

まとめ

  • Angulerfire2を使えば簡単にリアルタイムWEBアプリが作られる
  • Firebaseならホスティングも無料