Cloud Functions for Firebase を使ったお問い合わせフォーム実装
FirebaseはGoogleが提供するクラウドサービスの一つでWebサービスをリリースする上で必要な機能を多数揃えています。この記事ではWebサービスで需要の高いお問い合わせフォームをFirebaseで実装する方法について紹介します。
当記事で目指すこと
- 静的ホスティングしたコンテンツにお問い合わせフォームを実装する
- フォーム送信内容を指定のメールアドレスへ通知する
- フレームワークを使わないシンプルな構成で実装する
Firebaseにはフォームを簡易実装できる機能が標準で備わっていないためCloud FunctionsとNode.jsでメール送信できるNodemailerを利用します。またメールを送信するには通常メールサーバーが必要となります。そこで今回はGmailを使用することにします。
Firebaseプロジェクトの作成
Firebaseのコンソール画面から新規プロジェクトの作成を行ってください。Firebaseの利用が初めての方は以下記事の「Firebase でプロジェクトを作成する」を参照してください。
Gmailアカウントの準備
Gmailアカウントを用意してください。Gmailをメールサーバーとして利用する場合はGmailのセキュリティレベルを意図的に下げる必要があるため普段利用するアカウントとは別に用意することをおすすめします。
Gmailのセキュリティレベルは以下リンクから変更することができます。「安全性の低いアプリの許可」を有効にしてください。
ホスティング対象の用意
ホスティングしたいコンテンツを好きな方法で用意してください。
サンプルでは非常にシンプルなHTMLを用意しています。
フォーム送信時の処理はbody下部で読み込ませているindex.jsに記述します。このindex.jsはモージュールバンドラー(Webpack)を用いてエクスポートしています。
HTMLと空のJavaScriptファイルが用意できたらFirebaseをJavaScript
プロジェクトへ追加します。ここではnpm パッケージを使用していますが、CDNでも配信されています。
project-root
├── dist
| ├── index.html
| └── assets
| └── js
| └── index.js
├── package.json
└── その他ファイル省略
package.jsonがまだ作成されていなければ以下コマンドで作成してください。
npm init
Npm利用の場合は以下コマンドでパッケージをインストールします。
npm install --save firebase
*モジュールバンドラーなどの設定は割愛します。
パッケージのインストールが完了したらFirebaseの初期化処理を記述します。エントリーポイントとなるファイルに以下を記述します。
処理内容はデータ送信に必要な最低限の記述に留めています。バリデーションなどはプロジェクトに応じて適宜加えてください。
本サンプルでは記述がTypeScriptの仕様になっています。Vanilla JS で直接記述する場合は適宜処理内容を調整してください。
Firebaseの初期設定を以下のように記述します。
// firebaseのインポート
import * as firebase from "firebase";
// firebase設定
const config = {
apiKey: "api-key",
authDomain: "project-id.firebaseapp.com",
databaseURL: "https://project-id.firebaseio.com",
projectId: "project-id",
storageBucket: "project-id.appspot.com",
messagingSenderId: "sender-id",
};
firebase.initializeApp(config);
export const functions = firebase.functions();
config内の設定はFirebaseコンソール画面の「プロジェクトを設定」で確認することができます。
api-keyとproject-idはSettingsの全般で確認できますが、sender-idはクラウドメッセージングに記載されています。sender-idとは送信者IDを意味します。
Firebaseの初期化設定が完了したら、フォーム送信時の処理を記述します。まず特定IDを持つ入力項目から値の取得を行う関数を記述します。
// フォームの値取得
function getVal(id: string): string {
const element: HTMLInputElement = document.getElementById(
id
) as HTMLInputElement;
return element.value;
}
次にフォーム送信時の処理を記載します。上記で定義したgetVal関数を実行しフォームで入力された値を取得します。
// フォーム送信
function submitForm(e: any): void {
e.preventDefault();
const getName = getVal("name");
const getMail = getVal("email");
const mailer = functions.httpsCallable("sendMail");
// 中略
}
後述するsendMail関数をCloud Functionsから呼び出し、フォームから取得した値を引き渡します。ここではまだCloud Functionsに関数を定義していないため以下の仕様だけ理解しておいてください。
”Cloud Functions for Firebase のクライアント SDK を使用すると、Firebase アプリから関数を直接呼び出すことができます。この方法でアプリから関数を呼び出すには、Cloud Functions において HTTPS 呼び出し可能関数を記述してデプロイし、アプリから関数を呼び出すためのクライアント ロジックを追加します。”
const mailer = functions.httpsCallable("sendMail");
mailer({ name: getName, email: getMail })
.then(() => {
alert("お問い合わせ内容を送信しました!");
})
.catch(error => {
console.log(error);
})
.finally(() => {
console.log("処理が実行されました");
});
フロント側の処理は値の受け渡しと処理の判断だけになるため記述が抽象化されています。これでフロント側の記述は以上になります。
Firebaseプロジェクトの初期化
コンテンツの用意ができればFirebase CLIでFirebaseプロジェクトの初期化を行います。
firebase init
詳しい設定方法は以下記事の「Firebase CLIのインストール」以降を参考にしてください。
今回はHostingだけでなくCloud Functionsを利用するのでFunctionsも選択してください。
? Which Firebase CLI features do you want to set up for this folder? Press Space to select features, then Enter to confirm your choices. (Press <space> to select, <a> to toggle all, <i> to invert selection)
❯◯ Database: Deploy Firebase Realtime Database Rules
◯ Firestore: Deploy rules and create indexes for Firestore
◯ Functions: Configure and deploy Cloud Functions
◯ Hosting: Configure and deploy Firebase Hosting sites
◯ Storage: Deploy Cloud Storage security rules
◯ Emulators: Set up local emulators for Firebase features
デプロイする前にCloud Functions内で利用するパッケージのインストール、Cloud Functionsで実行する関数の定義、環境変数の設定をそれぞれ行います。
プロジェクトのルートディレクトリにfunctionsフォルダが確認できたら、以下コマンドでfunctionsディレクトリへ移動し、Nodemailerをインストールします。
// functionsディレクトリへ移動
cd functions
// Nodemailerインストール
npm install --save nodemailer
この時プロジェクト内の構成は以下のようになっているはずです。
project-root
├── dist
| ├── index.html
| └── assets
| └── js
| └── index.js
├──functions
| ├── index.js
| └── その他ファイル省略
├── package.json
└── その他ファイル省略
Nodemailerのインストールが完了したら以下処理をfunctionsフォルダ内のindex.jsに貼り付けます。
通知用のメールテンプレートをフォーム内容に合わせて変更することで通知内容のカスタマイズができます。
// 通知用メールテンプレート
const adminContents = data => {
return `お問い合わせを受けました。
お名前:
${data.name}
メールアドレス:
${data.email}
`;
};
メールサーバーとしてGmailを利用するにはGmailのログインIDとパスワードを用いて認証を通す必要があります。Gmailの認証情報や通知先のメールアドレスなどは直接functions/index.jsへ記述するのではなく環境変数として登録しておきます。
以下コマンドで認証情報を環境変数として登録します。
firebase functions:config:set gmail.email="GmailのログインID" gmail.password="Gmailのパスワード" admin.email="通知先メールアドレス"
登録した環境変数は以下のように呼び出せます。
const gmailEmail = functions.config().gmail.email;
const gmailPassword = functions.config().gmail.password;
const adminEmail = functions.config().admin.email;
以上の設定まで完了したら以下コマンドでデプロイを行ってください。
firebase deploy
デプロイ先のURLが表示されるのでアクセスして、フォームの送信が正しく行われるか確認してみてください。functionsが既にデプロイ済みであればローカル環境でもフォームの送信確認ができます。
正常に動作していれば以下のように通知先メールアドレスへフォームの内容が送信されているはずです。
まとめ
Firebaseは多様な機能が使える分、実装時には多少の学習コストが必要になります。ただ、学習コスト以上の恩恵をほぼ無料で受けることができるのは本当に驚きです。
参考・補足
Cloud Functionsを利用したフォーム実装に関する記事は既にいくつか公開されています。当記事は以下記事をかなり参考にさせていただきました。フレームワークを利用して実装される方はぜひ参照してみてください。
Nodemailerの日本語解説は以下記事がおすすめです。