5
4

More than 3 years have passed since last update.

Firebaseを使ってコメント機能を実装する

Last updated at Posted at 2021-02-10

はじめに

Webページにコメントフォームを埋め込み、閲覧者がコメントを投稿できる機能をシンプルに作りたいと思ったので、Firebaseを使ってコメントの保存と取得して一覧表示をする方法をご紹介します。

こんなものを作っていきます

画面収録-2021-02-10-22.22.45.gif

前提

  • 今回Firebaseを使うのでGoogleアカウントが必要です。
  • ReactやAngularなどを使ったほうがやりやすいですが、今回はピュアなJavaScriptを使って実装していきます。
  • 実装には関係ないですがデザインはUIKitを使いました。

Firebaseとは

Firebaseは、Googleが提供するモバイル及びWebアプリケーションのバックエンドサービスです(これをmBaaSと言います)
通常、今回のようなコメント機能を実装するには、Webページだけではなくコメントを保存するデータベースや送信されたデータを処理するためのサーバーを作成する必要がありますが、Firebaseを使えばこのサーバーをつくる工程が不要になるのでサービスの素早い開発をすることができるようになります。

まずはフォームだけを作っていく

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>コメント</title>
    <!-- UIkit CSS -->
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/uikit@3.6.16/dist/css/uikit.min.css"
    />

    <!-- UIkit JS -->
    <script src="https://cdn.jsdelivr.net/npm/uikit@3.6.16/dist/js/uikit.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/uikit@3.6.16/dist/js/uikit-icons.min.js"></script>
  </head>
  <body>
    <div class="uk-container uk-padding">
      <div
        class="uk-card uk-card-default uk-card-body uk-width-1-2@m uk-margin-auto"
      >
        <h2 class="uk-card-title">コメント</h2>
        <form class="uk-form-stacked" id="commentForm">
          <div class="uk-margin">
            <label for="nickname" class="uk-form-label">ニックネーム</label>
            <div class="uk-form-controls">
              <input
                id="nickname"
                type="text"
                name="nickname"
                class="uk-input"
                placeholder="名無しさん"
              />
            </div>
          </div>
          <div class="uk-margin">
            <label for="comment" class="uk-form-label">コメント</label>
            <div class="uk-form-controls">
              <textarea
                name="comment"
                id="comment"
                cols="30"
                rows="10"
                class="uk-textarea"
                required
              ></textarea>
            </div>
          </div>
          <div class="uk-margin-large uk-flex uk-flex-center">
            <button type="submit" class="uk-button uk-button-primary">
              コメントする
            </button>
          </div>
        </form>
        <hr class="uk-divider-icon">
        <ul class="uk-comment-list" id="commentContainer">
        </ul>
      </div>
    </div>
    <script type="text/javascript" src="script.js"></script>
  </body>
</html>

次にとりあえずJavaScriptでは送信するデータをconsole.logで表示します。

script.js
const form = document.getElementById('commentForm');
const nicknameInput = document.getElementById('nickname');
const commentInput = document.getElementById('comment');
const commentContainer = document.getElementById("commentContainer");

form.addEventListener('submit', (ev) => {
    console.log(nicknameInput.value, commentInput.value);
    ev.preventDefault();
})

ニックネームとコメントを入力して『コメントする』ボタンを押すとデベロッパーツールのコンソールに入力されたデータが表示されればOKです!
image.png

Firebaseのセットアップ

Firebaseのページにアクセスし画面右上の『ログイン』からログインしてください。
スクリーンショット 2021-02-10 23.13.51.png

ログインできたら『コンソールへ移動』からコンソールに移動してください。
スクリーンショット 2021-02-10 23.10.20.png

コンソールに移動したら『プロジェクトの作成』からプロジェクトを作成しましょう。
image.png

『プロジェクト名』と『Google Analytics』の設定をしてWebアプリケーションの追加をしましょう
image.png

『アプリのニックネーム』は何でも大丈夫です!
スクリーンショット 2021-02-10 23.18.41.png

アプリ名の登録が完了され表示されるHTMLタグをコピーしてindex.htmlのbodyタグの下部に追加してください。

index.html
  <body>

    <!-- 省略 -->

    <!-- ここから追加 -->
    <!-- The core Firebase JS SDK is always required and must be listed first -->
    <script src="https://www.gstatic.com/firebasejs/8.2.6/firebase-app.js"></script>

    <!-- TODO: Add SDKs for Firebase products that you want to use
            https://firebase.google.com/docs/web/setup#available-libraries -->

    <script>
      // Your web app's Firebase configuration
      var firebaseConfig = {
        apiKey: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        authDomain: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        projectId: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        storageBucket: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        messagingSenderId: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        appId: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
      };
      // Initialize Firebase
      firebase.initializeApp(firebaseConfig);
    </script>
    <!-- ここまで追加 -->

    <script type="text/javascript" src="script.js"></script>
  </body>

Firestoreのセットアップ

FirestoreはFirebaseのデータベースのサービスです。
左のメニューの構築の中のCloud Firestoreにアクセスし『データーベースを作成』を押してください
image.png

セキュリティー保護ルールはここではテストモードにしてください
image.png

ロケーションはFirestoreのドキュメントによるとasia-northeast1が東京のようなのでとりあえずasia-northeast1にして『有効にする』を押して作成を完了してください。
image.png

FirestoreのSDKをindex.htmlに貼り付けてください。

これをコピーしてください
<script src="https://www.gstatic.com/firebasejs/8.2.1/firebase-firestore.js"></script>

まえにFirebaseからコピペしたコードの周辺に貼り付ければOKです!

index.html
    <!-- The core Firebase JS SDK is always required and must be listed first -->
    <script src="https://www.gstatic.com/firebasejs/8.2.6/firebase-app.js"></script>

    <!-- ここから追加 -->
    <script src="https://www.gstatic.com/firebasejs/8.2.1/firebase-firestore.js"></script>
    <!-- ここまで追加 -->

Firestoreにデータを保存する

Firestoreにデータを保存するときは次のようなコードになります。

Firestoreにデータを保存するとき
const db = firebase.firestore();
db.collection('コレクション名')
  .add(データ)
  .then(() => {
    // 保存が完了したときの処理
  })
  .catch((err) => {
    // エラーが発生したときの処理
  }); 

コレクションというのはデータを保存しておくフォルダのようなものです。
image.png
引用:Cloud Firestore | Firebase

それではコメントをFirestoreに保存する処理を書いてきましょう

script.js
const form = document.getElementById("commentForm");
const nicknameInput = document.getElementById("nickname");
const commentInput = document.getElementById("comment");
const commentContainer = document.getElementById("commentContainer");

// firestoreのインスタンスを初期化
const db = firebase.firestore();

form.addEventListener("submit", (ev) => {
  // formが送信されるのを防ぐ
  ev.preventDefault();

  // 1.formDataのオブジェクトを作成
  const formData = {
    nickname: nicknameInput.value || "名無しのジャクソン",
    comment: commentInput.value,
  };

  console.log(formData);

  // 2.firebaseにデータを送信
  db.collection("comments")
    .add(formData)
    .then(() => {
      console.log("送信されました");

      // フォームの内容を削除
      nicknameInput.value = "";
      commentInput.value = "";
    })
    .catch((err) => {
      console.error("エラーが発生しました:", err);
    });
});

一気に長くなりましたね。ですがやっていることは単純で
1. formDataのオブジェクト作成する(nicknameが空のときは「名無しのジャクソン」がセットされるようにしています)
2. Firestoreにデータを送信
の2つです。

正しく出来ていればFirestoreのデータに送信した内容が保存されていると思います。
スクリーンショット 2021-02-11 0.07.39.png

Firestoreからデータを取得する

Firestoreに保存することができるようになったので、次はFirestoreに保存されているデータを取得して表示してましょう。

Firestoreからデータを取得するときは次のようなコードになります。

Firestoreからデータを取得するとき
db.collection("コレクション名")
  .get()
  .then((querySnapshot) => {
    querySnapshot.forEach((doc) => {
      // コレクションに格納されているデータ1つ1つに対する処理
      // doc.data()でデータを取得できる
      console.log(doc.data());
    });
  });

それではFirestoreからコメント一覧を取得して表示するコードを書いていきましょう

script.js
const form = document.getElementById("commentForm");
const nicknameInput = document.getElementById("nickname");
const commentInput = document.getElementById("comment");
const commentContainer = document.getElementById("commentContainer");

// firestoreのインスタンスを初期化
const db = firebase.firestore();

// 最初にコメント一覧を取得して表示する。
window.addEventListener("load", (ev) => {updateComment()});

form.addEventListener("submit", (ev) => {
  // formが送信されるのを防ぐ
  ev.preventDefault();

  // formDataのオブジェクトを作成
  const formData = {
    nickname: nicknameInput.value || "名無しのジャクソン",
    comment: commentInput.value,
  };

  console.log(formData);

  // firebaseにデータを送信
  db.collection("comments")
    .add(formData)
    .then(function () {
      console.log("送信されました");
      nicknameInput.value = "";
      commentInput.value = "";

      // コメントの保存が成功したら、コメントの一覧を取得して表示する
      updateComment();
    })
    .catch(function (err) {
      console.error("エラーが発生しました:", err);
    });
});

// コメント一覧を更新する関数
function updateComment() {
  db.collection("comments")
    .get()
    .then((querySnapshot) => {
      // コメント一覧の配列
      const comments = [];

      querySnapshot.forEach((doc) => {
        comments.push(doc.data());
      });

      renderComment(comments);
    });
}

// コメントを描画する関数
function renderComment(comments) {
  commentContainer.innerHTML = '';
  comments.forEach((comment) => {
    commentContainer.innerHTML += createCommentNode(comment);
  });
}

// コメントのノードを作成してくれる関数
function createCommentNode(comment) {
  return `<li>
    <div class="uk-comment uk-comment-primary">
      <div class="uk-comment-header">
        <h5 class="uk-comment-title">${comment.nickname}</h5>
      </div>
      <div class="uk-comment-body">
        ${comment.comment}
      </div>
    </div>
  </li>`;
}

ここまで問題なくできていれば、最初と同じように読み込み時に投稿されているコメント一覧が表示されており、コメントの投稿が完了したときには新たに投稿したコメントが追加されると思います。

画面収録-2021-02-10-22.22.45.gif

おわりに

今回、Firebaseを使ったコメント機能をピュアなJavaScriptで実装していきました。
バックエンドの実装が必要ないので1時間もかからないで実装できましたが、普段VueやReactなどのJavaScriptフレームワークを使っているのでピュアJavaScriptでコードを記述するのはやっぱりめんどくさいなと思いました。
また、FirebaseのAPIキーなどをそのままindex.htmlに埋め込んでいるため、これを見られてしまえば、勝手に他のページからもコメントを書き込まれてしまうと思います。実際にサービスとして実装する際にはそのへんのことも考慮に入れる必要があるでしょう。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4