はじめに
Webページにコメントフォームを埋め込み、閲覧者がコメントを投稿できる機能をシンプルに作りたいと思ったので、Firebase
を使ってコメントの保存と取得して一覧表示をする方法をご紹介します。
こんなものを作っていきます
前提
- 今回
Firebase
を使うのでGoogleアカウントが必要です。 - ReactやAngularなどを使ったほうがやりやすいですが、今回はピュアなJavaScriptを使って実装していきます。
- 実装には関係ないですがデザインは
UIKit
を使いました。
Firebaseとは
Firebaseは、Googleが提供するモバイル及びWebアプリケーションのバックエンドサービスです(これをmBaaS
と言います)
通常、今回のようなコメント機能を実装するには、Webページだけではなくコメントを保存するデータベースや送信されたデータを処理するためのサーバーを作成する必要がありますが、Firebase
を使えばこのサーバーをつくる工程が不要になるのでサービスの素早い開発をすることができるようになります。
まずはフォームだけを作っていく
<!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
で表示します。
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です!
Firebaseのセットアップ
Firebaseのページにアクセスし画面右上の『ログイン』からログインしてください。
ログインできたら『コンソールへ移動』からコンソールに移動してください。
コンソールに移動したら『プロジェクトの作成』からプロジェクトを作成しましょう。
『プロジェクト名』と『Google Analytics』の設定をしてWebアプリケーションの追加をしましょう
アプリ名の登録が完了され表示されるHTMLタグをコピーしてindex.html
のbodyタグの下部に追加してください。
<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
にアクセスし『データーベースを作成』を押してください
セキュリティー保護ルールはここではテストモード
にしてください
ロケーションはFirestoreのドキュメントによるとasia-northeast1
が東京のようなのでとりあえずasia-northeast1
にして『有効にする』を押して作成を完了してください。
FirestoreのSDKをindex.html
に貼り付けてください。
<script src="https://www.gstatic.com/firebasejs/8.2.1/firebase-firestore.js"></script>
まえにFirebaseからコピペしたコードの周辺に貼り付ければOKです!
<!-- 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にデータを保存するときは次のようなコードになります。
const db = firebase.firestore();
db.collection('コレクション名')
.add(データ)
.then(() => {
// 保存が完了したときの処理
})
.catch((err) => {
// エラーが発生したときの処理
});
コレクションというのはデータを保存しておくフォルダのようなものです。
引用:Cloud Firestore | Firebase
それではコメントをFirestoreに保存する処理を書いてきましょう
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);
});
});
一気に長くなりましたね。ですがやっていることは単純で
- formDataのオブジェクト作成する(nicknameが空のときは「名無しのジャクソン」がセットされるようにしています)
- Firestoreにデータを送信
の2つです。
正しく出来ていればFirestoreのデータに送信した内容が保存されていると思います。
Firestoreからデータを取得する
Firestoreに保存することができるようになったので、次はFirestoreに保存されているデータを取得して表示してましょう。
Firestoreからデータを取得するときは次のようなコードになります。
db.collection("コレクション名")
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
// コレクションに格納されているデータ1つ1つに対する処理
// doc.data()でデータを取得できる
console.log(doc.data());
});
});
それではFirestoreからコメント一覧を取得して表示するコードを書いていきましょう
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>`;
}
ここまで問題なくできていれば、最初と同じように読み込み時に投稿されているコメント一覧が表示されており、コメントの投稿が完了したときには新たに投稿したコメントが追加されると思います。
おわりに
今回、Firebaseを使ったコメント機能をピュアなJavaScriptで実装していきました。
バックエンドの実装が必要ないので1時間もかからないで実装できましたが、普段VueやReactなどのJavaScriptフレームワークを使っているのでピュアJavaScriptでコードを記述するのはやっぱりめんどくさいなと思いました。
また、FirebaseのAPIキーなどをそのままindex.html
に埋め込んでいるため、これを見られてしまえば、勝手に他のページからもコメントを書き込まれてしまうと思います。実際にサービスとして実装する際にはそのへんのことも考慮に入れる必要があるでしょう。