pco2699’s blog

学んだものについて、メモしておく場所

Firebase AuthとExpress + Typescript + Sequelizeで認証機能を作ろう

こんにちは、この記事はfirebase advent calendar 13日目の記事です。

TL;DR

  • Firebase AuthとExpressを連携させて、認証機能を作ってみよう
  • その他、今後の開発のしやすさも考えてTypescriptと Sequelizeも使ってみます。
  • 結果として、FirebaseというよかExpressの記事になってしまいましたサーセン

今回つくるもの

今回は、以下のようなアーキテクチャで作ってみたいと思っています。 案外、こういうアーキテクチャで認証機能作ってるところ多いと思うんですが 自分で探してみても、記事自体はあんまりなかったです。

f:id:pco2699:20181213231619p:plain

Typescript/Expressのセットアップ

基本的なTypescript/Expressのディレクトリ構成やセットアップは↓のTypescript/Expressの公式Sampleを多いに参考にしました。
やっぱ参考にすべきは公式よね〜

Webpackがなんだか苦手なので、このレポジトリの通り、tscを使って愚直にコンパイルしてます。 必要になったら導入したいと思ってます。

github.com

ディレクトリ構成は以下のような感じとなっています。 (案件の都合上、ソースコードをオープンに出来ないためスクショで失礼)

f:id:pco2699:20181214185545p:plain

概ね、Expressの入門とかGithubサンプルを見つつ、オーソドックスなディレクトリ構成にしました。

Firebaseのセットアップ

firebaseのセットアップは、開発環境・本番環境と分けるためそれぞれ別のfirebaseプロジェクトを紐づけています。 紐づけ方は、dotenvを利用して、それをfirebaseに読み込ませるような形です。

具体的には、以下の通り

// ./config/index.ts

// まずはdotenvを読み込ませる
import dotenv from 'dotenv';

// NODE_ENVの設定内容に応じて、読み込む.envファイルを読み替える
dotenv.config({
  path: `${__dirname}/environment/.env.${process.env.NODE_ENV}`,
});

こちらをexpressを立ち上げるスタートポイントの最初に読み込ませます。
こうしないと、先にfirebaseの読み込みが走ってしまい、firebaseがundifinedで初期化されてしまいます。

// ./server.ts

// 頭で先程のconfigを読み込ませる
import '.config';

後はprocess.envでfirebaseを初期化すればOKです。

import firebase from 'firebase';

const config = {
  apiKey: process.env.API_KEY,
  authDomain: process.env.AUTH_DOMAIN,
  databaseURL: process.env.DATABASE_URL,
  storageBucket: process.env.STORAGE_BUCKET,
  messagingSenderId: process.env.MESSAGING_SENDER_ID,
};

firebase.initializeApp(config);

export default firebase;

実際の.envファイルは以下のような形で格納されています。

Sequelizeのセットアップ

次にSequelizeのセットアップを行います。
Sequelize + Typescriptの情報はなかなかまとまった情報が無く、個人的に非常に苦労しました...

必要なパッケージのインストール

まずは、Sequelizeを利用するのに以下の必要なパッケージを入れておきます。

$ npm install --save sequelize sequelize-typescript sequelize-cli-typescript

次に、Sequelizeがどのファイルを読み込ませるかの情報を教えるため、.sequelizercを プロジェクトルートに作成します。

// .sequelizerc
var path = require('path')

module.exports = {
  'config':          path.resolve('src', 'db', 'config', 'db_config.json'),
  'migrations-path': path.resolve('src', 'db', 'migrations'),
  'models-path':     path.resolve('src', 'db', 'models'),
  'seeders-path':    path.resolve('src', 'db', 'seeders'),
}

すいません、時間が無くなってしまったため、後日以降の章を更新させていただきますm( )m