LoginSignup
8
9

More than 3 years have passed since last update.

【勉強会用資料】Cloud Functions for FirebaseとFirebase Hostingを使い、ベーシック認証付きステージング環境と本番環境を用意する

Last updated at Posted at 2019-08-25

勉強会用に作成した、Cloud Functions for FirebaseとFirebase Hostingを使い、ベーシック認証付きステージング環境と本番環境を用意するまでのフローです。

以下の内容を学ぶことができます。

  • Git(GitHub)入門
  • Firebase Hosting と Cloud Functions for Firebase 入門
    • ほんのりTypeScript

始めるまえに、以下の設定が必要です。

  • GitHubアカウント
  • Googleアカウント
  • ローカル環境にNode.jsのインストール(version 8 以上)

GitHubのリポジトリを作成

  1. 「New repository」でリポジトリを新規作成
  2. 「Clone or download」でURLを取得しクローン
  3. 任意の場所でプロジェクト用ディレクトリを作成
  4. クローンしたディレクトリにターミナルで移動
$ mkdir demo-project
$ git clone <github-url>
$ cd demo-projecy

developブランチの作成

ターミナルでブランチを作成

$ git checkout -b develop

ベーシック認証の環境

Firebaseのプロジェクトを作成

コンソールで新規プロジェクト作成

firebaseの設定

$ firebase login
$ firebase init
  1. Functions: Configure and deploy Cloud Functionsを選択
  2. Firebase Consoleで作成したプロジェクトを選択
  3. せっかくなのでTypeScriptを選択
  4. Do you want to use TSLint to catch probable bugs and enforce style? -> n(TSLintよりも、ESLintが良いかと思うのでここはNoで)
  5. Do you want to install dependencies with npm now? -> [enter](npm installしてくれます)

開発環境の構築

リダイレクト用ホスティングディレクトリ作成

public/
  └ placeholder.html

Webページの本体になるディレクトリを作成
nuxt generate等で出力する場合は、そのディレクトリ)

表示確認ようにダミーのindex.htmlを作成しておく

functions/
  └ dist/
    └ index.html

package.jsonpackage-lock.jsonを移動

functions/
  ├ package.json
  └ package-lock.json

functions/
package.json
package-lock.json

npm scriptを書き換え

  "scripts": {
    "build": "tsc --project functions",
    "preserve": "npm run build && npm run copy-deps && npm run install-deps",
    "serve": "npm run build && firebase serve",
    "shell": "npm run build && firebase functions:shell",
    "start": "npm run shell",
    "init-deploy": "firebase deploy",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log",
    "copy-deps": "cpx \"*{package.json,package-lock.json,yarn.lock}\" \"functions\" -C",
    "install-deps": "cd functions && npm install && cd ../"
  }

パッケージの追加

$ npm i express basic-auth-connect && npm i -D @types/express cpx

firebase.jsonの書き換え

{
  "functions": {
    "source": "functions",
    "predeploy": "npm run preserve"
  },
  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "function": "stagingApp"
      }
    ]
  }
}

function/src/index.tsに以下を記述

import * as functions from 'firebase-functions';
import * as express from 'express';

// 型定義ファイルを作るのが面倒なので妥協。。。
const basicAuth = require('basic-auth-connect');

const user = 'user';
const pass = 'pass';

const server = express();
server.use(basicAuth(user, pass));
server.use(express.static('./dist'));

export const stagingApp = functions.https.onRequest(server);

function/src/index.tsをビルドしてローカルサーバー立ち上げ

$ npm run serve

機密情報を環境変数に変更

このままだとベーシック認証のアイパスが見えてしまうので環境変数に格納

$ cd functions
$ firebase functions:config:set basicauth.user="<yourUserName>" basicauth.pass="<yourPassword>"

設定した環境変数は以下で確認できる

$ firebase functions:config:get

ローカルサーバーでも使えるように、functions/.runtimeconfig.jsonを作成

$ firebase functions:config:get > .runtimeconfig.json
$ cd ../

.gitignore.runtimeconfig.jsonを追加してgit管理から外す(リモートにプッシュ禁止)

また、functions/配下にもnode_modulespackage.jsonが必要なため、以下のコマンドで複製しインストールしておく

(ローカルサーバー立ち上げ、デプロイ時にも実行されます)

$ npm run copy-deps && npm run install-deps

function/src/index.tsを修正

import * as functions from 'firebase-functions';
import * as express from 'express';

// 型定義ファイルを作るのが面倒なので妥協。。。
const basicAuth = require('basic-auth-connect');

// 環境変数
const user = functions.config().basicauth.user;
const pass = functions.config().basicauth.pass;

const server = express();
server.use(basicAuth(user, pass));
server.use(express.static('./dist'));

export const stagingApp = functions.https.onRequest(server);

ローカルサーバーで確認

$ npm run serve

publicディレクトリをアップするため、以下を実行

$ npm run init-deploy

次回以降は、publicディレクトリをアップしないので、以下でOK

$ npm run deploy

コミットしてGitHubにプッシュ

$ git add .
$ git commit -m "コミットメッセージ"
$ git push origin HEAD

本番環境

firebaseで本番環境も対応する場合は切り替えが必要なので対応

コンソールで新規プロジェクト作成

今回は2種類の本番環境を用意

  • 静的ホスティング
    • 静的なサイトであれば十分
    • Cloud Functions for Firebase を経由しないのでパフォーマンス的には少し有利?
  • Expressをそのまま使用
    • Node.jsが使える
      • よって、ExpressじゃなくてもOK

環境構築(静的ホスティング)

developブランチから新たにブランチを作成

$ git checkout -b static_hosting

作成した本番用プロジェクトのホスティング情報を.firebasercに追加

$ firebase target:apply hosting production <production-project-id>
$ firebase target:apply hosting staging <staging-project-id>

firebase.jsonに環境別のホスティング情報を追記

  {
    "functions": {
      "source": "functions",
      "predeploy": "npm run preserve"
    },
+   "hosting": [{
+     "target": "staging",
+     "public": "public",
+     "ignore": [
+       "firebase.json",
+       "**/.*",
+       "**/node_modules/**"
+     ],
+     "rewrites": [
+       {
+         "source": "**",
+         "function": "stagingApp"
+       }
+     ]
+   },
+   {
+     "target": "production",
+     "public": "functions/dist",
+     "ignore": [
+     "firebase.json",
+       "**/.*",
+       "**/node_modules/**"
+     ]
+   }]
  }

package.jsonの書き換え

  "scripts": {
    "build": "tsc --project functions",
    "preserve": "npm run build && npm run copy-deps && npm run install-deps",
    "serve": "npm run build && firebase serve",
    "shell": "npm run build && firebase functions:shell",
    "start": "npm run shell",
    "deploy-init": "firebase deploy",
-   "deploy": "firebase deploy --only functions",
+   "deploy-staging": "firebase deploy --only functions",
+   "deploy-production": "firebase deploy --only hosting:production",
    "logs": "firebase functions:log",
    "copy-deps": "cpx \"*{package.json,package-lock.json,yarn.lock}\" \"functions\" -C",
    "install-deps": "cd functions && npm install && cd ../"
  },

ステージングにデプロイ

$ npm run deploy-staging

本番にデプロイ

$ npm run deploy-production

環境構築(Express環境)

一度、developブランチに戻り、express_hostingブランチを新たに作成

$ git checkout develop
$ git checkout -b express_hosting

作成した本番用プロジェクトを指定し、エイリアスを設定

$ firebase use --add
$ What alias do you want to use for this project? (e.g. staging)

.firebasercにプロジェクトが追加される(今回はproductionというエイリアスで登録)

もともとのdefaultエイリアスはわかりやすい名前に変えてOK(以下はstagingに変更)

{
  "projects": {
-   "default": "<staging-project-id>",
+   "staging": "<staging-project-id>",
+   "production": "<production-project-id>"
  }
}

firebase.jsonも変更

{
  "functions": {
    "source": "functions",
    "predeploy": "npm run preserve"
  },
  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
-       "function": "stagingApp"
+       "function": "app"
      }
    ]
  }
}

npm scriptにプロジェクトの切り替えタスクを追加

  "scripts": {
    "build": "tsc --project functions",
    "preserve": "npm run build && npm run copy-deps && npm run install-deps",
    "serve": "npm run build && firebase serve",
    "shell": "npm run build && firebase functions:shell",
    "start": "npm run shell",
    "init-deploy": "firebase deploy",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log",
    "copy-deps": "cpx \"*{package.json,package-lock.json,yarn.lock}\" \"functions\" -C",
    "install-deps": "cd functions && npm install && cd ../",
+   "env-staging": "firebase use staging",
+   "env-production": "firebase use production"
  }

プロジェクト切り替えが可能になる

$ npm run env-xxx

本番環境でベーシック認証解除

環境変数をクローンし、問題がないか確認

$ firebase functions:config:clone --from <project-id>
$ firebase functions:config:get

以下のディレクトリとファイルを作成

functions/src
  └ app
    ├ app.ts
    ├ index.ts
    ├ productionApp.ts
    └ stagingApp.ts

functions/src/app/stagingApp.ts

import * as functions from 'firebase-functions';
import * as express from 'express';

// 型定義ファイルを作るのが面倒なので妥協。。。
const basicAuth = require('basic-auth-connect');

const user = functions.config().basicauth.user;
const pass = functions.config().basicauth.pass;

const server = express();
server.use(basicAuth(user, pass));
server.use(express.static('./dist'));

export const stagingApp = functions.https.onRequest(server);

functions/src/app/productionApp.ts

import * as functions from 'firebase-functions';
import * as express from 'express';

const server = express();
server.use(express.static('./dist'));

export const productionApp = functions.https.onRequest(server);

functions/src/app/app.ts

import { productionApp } from './productionApp';
import { stagingApp } from './stagingApp';

const isStaging = process.env.GCLOUD_PROJECT === '<staging-project-id>';
export const app = isStaging ? stagingApp : productionApp;

functions/src/app/index.ts

export { app } from './app';

functions/src/index.tsを書き換え

export { app } from './app';

本番環境用ローカルサーバーを立ち上げ

$ npm run env-production
$ npm run serve

テスト環境用ローカルサーバーを立ち上げ

$ npm run env-staging
$ npm run serve

本番環境にデプロイ

$ npm run env-production
$ npm run init-deploy

次回以降は、以下でOK

$ npm run env-production
$ npm run deploy

テスト環境にデプロイ

$ npm run env-production
$ npm run deploy

コミットしてGitHubにプッシュ

$ git add .
$ git commit -m "コミットメッセージ"
$ git push origin HEAD

最後にGitHubでプルリクエストを作り、developブランチにマージしてみましょう!

8
9
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
8
9