なになれ

IT系のことを記録していきます。

AngularとFirebaseでWebアプリを作った

AngularとFirebaseでWebアプリを作ったので、その記録です。

作ったものがこちらです。
友達同士で本を共有できるみんなの本棚というコンセプトで、本を登録し、持っている本を友達同士で共有できるサービスです。
bookshelf-share.site

この記事では、このサービスを作るにあたって活用している技術について紹介します。

Webアプリのクライアント部分をカバーしているAngularですが、
さらにFirebaseを活用することでバックエンドのアプリなしでWebアプリを作成できます。

Angular

画面を作るためのベースのフレームワークとして利用しました。
Angular Docs

Angular Material

Angularにマテリアルデザインコンポーネントを提供するライブラリです。
Angular Material

Paginator
ページ数をつけるコンポーネントを活用しました。
こんな感じのコンポーネントを簡単に配置できます。 f:id:hi1280:20180310181123p:plain pageEventでページ数を変えた時の処理を記述できます。

paginator.html

<mat-paginator [length]="length"
              [pageSize]="pageSize"
              [pageSizeOptions]="pageSizeOptions"
              (page)="pageEvent = $event">
</mat-paginator>

AngularFire

AngularからFirebaseを利用するためのライブラリです。
GitHub - angular/angularfire2: The official Angular library for Firebase.

Firebase

バックエンドの機能を備えたサービスです。
認証、データベース、ホスティングの機能などがあります。
Firebase

認証

Firebaseのデータベース機能を使うために認証が実用上必須になります。

Googleログインによる認証
認証をGoogleログインに任せる形で実装できます。

app.component.ts

export class AppComponent {
  user: firebase.User;
  constructor(private afAuth: AngularFireAuth, private router: Router) {
    afAuth.authState.subscribe(user => this.user = user);
  }

  login() {
    this.afAuth.authState.subscribe((user) => {
      if (user && user.uid) {
        this.router.navigate(['main']);
      } else {
        this.afAuth.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider());
      }
    });
  }

  logout() {
    this.router.navigate(['home']);
    this.afAuth.auth.signOut();
  }
}

Googleだけでなく、FacebookTwitterGitHubのアカウントを利用することもできます。

データベース

クライアントから直接データベースを操作することができます。

Realtime Database
本の一覧を取得するのにクエリを活用して以下のようなコードを書きました。
データ作成の降順でソートしつつ、ページングに対応しています。

books.component.ts

private getBooks(pageSize: number, page: number) {
  this.db.list('books', ref => ref.orderByKey()).snapshotChanges().subscribe((books) => {
    const book = books[pageSize * page];
    // orderByKeyはkeyで昇順にする。昇順によるソートしか対応していない。
    // limitToFirstはデータの取得するに制限をかける。
    // startAtは取得するデータ開始位置を表す。ここではページング対応のために利用している。
    this.booksRef = this.db.list('books', ref => ref.orderByKey().limitToFirst(this.pageSize).startAt(book.key));
    // keyを使うためのコード
    this.books = this.booksRef.snapshotChanges().map(changes => {
      return changes.map(c => ({ key: c.payload.key, ...c.payload.val() }));
    // 降順にする
    }).map((changes) => changes.reverse());
    this.length = books.length;
  });
}

ホスティング

Angularで作成したWebアプリをFirebaseでホスティングできます。

Angularのアプリをビルドします。

$ ng build --prod

FirebaseのCLIツールをインストールします。

$ npm install -g firebase-tools

Firebaseのプロジェクトとして初期設定をします。

$ firebase init

以下のように質問に答えます。

? What do you want to use as your public directory?
dist

? Configure as a single-page app (rewrite all urls to /index.html)?
y

? File dist/index.html already exists. Overwrite?
N

デプロイします。

$ firebase deploy

注意点

Realtime Databaseはクエリ操作が特殊な感じで、機能も充実していないので使う時には注意が必要です。
少なくとも複雑な検索はできません。