【Next.js】Cloud Firestoreへの接続方法まとめ

f:id:nekorokkekun:20190923081808p:plain:w1000
Next.jsからCloud Firestoreへの接続をするための方法をまとめておきます。

まずやること

忘れがちなDB設定でやるべきことをまとめておきます。

  • .env作成
  • dotenvのインストール
  • next.config.js作成
  • lib/db.js作成

この4つに関しては自分も忘れがちなので、改めてまとめておきます。

.env作成

ルートディレクトリに.envファイルを作成し、Firestoreから取得したDB情報を成形して記述します。

FIREBASE_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxx
FIREBASE_AUTH_DOMAIN=xxxxxxxxxxxxxxxxxxxxxxxx
FIREBASE_DATABASE_URL=xxxxxxxxxxxxxxxxxxxxxxxx
FIREBASE_PROJECT_ID=xxxxxxxxxxxxxxxxxxxxxxxx
FIREBASE_STORAGE_BUCKET=xxxxxxxxxxxxxxxxxxxxxxxx
FIREBASE_MESSAGING_SENDER_ID=xxxxxxxxxxxxxxxxxxxxxxxx
FIREBASE_APP_ID=1:xxxxxxxxxxxxxxxxxxxxxxxx

「""」や「,」はいりません。

dotenvのインストール

.envで変数化したパスワード群を他のファイルで使用する場合、npmやyarnで「dotenv」というモジュールをインストールしておく必要があります。

dotenv - npm

# with npm 
npm install dotenv
 
# or with Yarn 
yarn add dotenv

next.config.js作成

他ファイルで.envの変数を使用するためには、変数名の前に「process.env.」を付ける必要があります。

apiKey: process.env.FIREBASE_API_KEY

そのためお決まりのファイルをルートディレクトリに作成しておきましょう。

next.config.js

const webpack = require('webpack');
require('dotenv').config();

module.exports = {
  webpack: config => {
    const env = Object.keys(process.env).reduce((acc, curr) => {
      acc[`process.env.${curr}`] = JSON.stringify(process.env[curr]);
      return acc;
    }, {});

    config.plugins.push(new webpack.DefinePlugin(env));

    return config;
  }
};

難しい内容ですが「process.env.」を使用できるようにしている、と考えてもらえればOKです。(ちなみにこのファイルがなければ、変数の中身が「undefined」となってしまいます)

lib/db.js作成

最後にDB接続を可能とするためのファイルを作成しましょう。

lib/db.js

import firebase from 'firebase/app'
import 'firebase/firestore'

let db;
try {
  const config = {
        apiKey: process.env.FIREBASE_API_KEY,
        authDomain: process.env.FIREBASE_AUTH_DOMAIN,
        databaseURL: process.env.FIREBASE_DATABASE_URL,
        projectId: process.env.FIREBASE_PROJECT_ID,
        storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
        messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
        appId: process.env.FIREBASE_APP_ID
    };
    if (!firebase.apps.length) {
      firebase.initializeApp(config);
    }
    // Firestoreインスタンスを作成
    db = firebase.firestore();
  } catch (error) {
    console.log(error);
  }

  module.exports = {
    // 本来、initializeAppによる初期化は一度きりのため、
    // 初期化の結果のみを切り出してexportする
    db
  };

これでDB接続ができるようになりました。

具体的な使用例

こんな感じで、db.jsで作成した変数dbを使用できるようになります。

// dbのインポート
import { db } from '../lib/db';
import React from 'react'

 export default class Posts extends React.Component {
  static async getInitialProps() {
    // db.jsのfirebaseのDB接続ファンクション
    // DBのpostsコレクション内を全て取得した結果 = result
    let result = await new Promise((resolve, reject) => {
      db.collection('posts')
      .get()
      .then(snapshot => {
        let data = []
        snapshot.forEach((doc) => {
          data.push(
            Object.assign({
              id: doc.id
            }, doc.data())
          )
        })
        resolve(data)
      }).catch(error => {
        reject([])
      })
    })
    return {posts: result}
  }

  handleDelete = (id) => {
    console.log(id)
  }

  render() {
    const posts = this.props.posts
    return (
        <React.Fragment>
                {posts.map(post =>
                    <div className="post" key={post.id}>
                        <h2>
                            {post.title}
                        </h2>
                        <p>
                            {post.body}
                        </p>
                        <button onClick={this.handleDelete.bind(this, post.id)}>削除</button>
                    </div>
                    )}
            <style jsx>{`
            .post {
                width: 40%;
                border: 1px solid black;
                background-color: gray;
                margin-bottom: 10px;
            }
            `}</style>
        </React.Fragment>
    );
  }
}