水無瀬のプログラミング日記

プログラムの勉強した時のメモ

Firebase Functionsを定期実行する

はじめに

Firebase Functionsで定期実行をできることを知ったので今回はそれを試してみる。

TL;DR.

試したソースコード
(既存のプロジェクトでやったため、最小構成ではない)

Firebase(+ GCP)の設定

プロジェクト作成

f:id:minase_mira:20200303233157p:plainf:id:minase_mira:20200303233202p:plainf:id:minase_mira:20200303233208p:plain
Firebaseプロジェクト作成
WebUIからポチポチ設定していく。
名前決めるくらいなのでサクッとすすめる。
アナリティクスはいらなかったので無効にする。

f:id:minase_mira:20200303233211p:plain プロジェクト作成できたら左上の歯車からSetting画面を開く。
定期実行する場合Google Cloud Platform(GCP)リソース ロケーションを設定する必要があるので、
好きなロケーションを選択する。(今回はasia-northeast1(東京)にしておく)

作成したプロジェクトが無料プラン(Spark)だった場合、従量課金制のBlazeにしておく。
(定期実行するのに必要)

GCPの設定

Cloud Scheduler APICloud Pub/Sub APIを有効にする必要がある。
APIライブラリから有効にしておく。

Firebase CLIの設定

# firebaseにログイン
$ firebase login

# firebase functions 初期設定
$ firebase init functions
> 色々聞かれるので好みの設定をする
> .firebasercとfirebase.json、functionsディレクトリが作成されていればOK

デプロイするフォルダを変更する

デフォルトの設定では作成されたfunctionsディレクトリにあるpackage.jsonを参照してデプロイされる。
このpackage.jsonで依存とか解決しているらしい。
※初期設定だとfunctions/lib/index.jsがデプロイ先になる。

ただ、今回はすでにあるプロジェクトをデプロイしたかったので、そのへんを変更していく。
(+階層が1段ずれるのもデプロイのためだけに変更するのも嫌だったので)

変更するにはfirebase.json"source": "."を追加すれば良い。
(今回はカレントディレクトリにしたかったため.)
合わせてpredeployfunctions配下のpackage.jsonを見るようprefixが付いていたので消しておく。

{
  "functions": {
    "source": ".",
    "predeploy": "npm run build"
  }
}

定期実行するコードを書いていく

公式のサンプルを参考にしながら書いていく。

export const sampleJob = functions
  // regionはGCPリソース ロケーションと合わせる
  .region('asia-northeast1')
  // 時間設定。よくあるcronの書き方もできる
  .pubsub.schedule('every day 07:00')
  // 時間指定しているので、一応タイムゾーンを設定しておく
  .timeZone('Asia/Tokyo')
  .onRun(context => {
    // 処理
  }

webpackの設定

webpackでバンドルした結果をデプロイしたかったので設定していく。
多分firebase用の設定はあまりないはず。

const path = require('path');
const nodeExternals = require('webpack-node-externals');

module.exports = {
  mode: 'production',
  entry: path.join(__dirname, '/app.ts'),
  target: 'node',
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: [
          {loader: 'ts-loader'},
          {loader: 'eslint-loader'}
        ],
        exclude: /node_modules/
      },
      {
        test: /\.node$/,
        use: 'node-loader'
      }
    ]
  },
  resolve: {
    extensions: ['.js', '.json', '.ts'],
    modules: [path.join(__dirname, 'src'), 'node_modules']
  },
  output: {
    // これを設定しないとうまくデプロイされなかった
    libraryTarget: 'this',
    path: path.join(__dirname, 'dist'),
    filename: 'app.js'
  },
  externals: [nodeExternals()]
};

環境変数を設定する

パスワードなどコード上に書きたくないものを環境変数に設定していく。
公式のサンプルを真似てすすめる。

# 環境変数にslackのwebhookURLを設定
$ firebase functions:config:set slack.url=https://hooks.slack.com/services/XXX

取り出すには下記のようにする。

import { config } from 'firebase-functions';
const slackUrl = config().slack.url;

デプロイする

firebase deploy —only functionsでOK。
ただし、deploy complete!とか言いながら失敗することがあるので、
Webコンソールを確認してデプロイが完了してることを確認した方が良いかも。

まとめ

Firebase Functionsで定期実行する方法をまとめた。
今まで定期実行したい処理がある時はLambdaを使ってたけど、今後はfirebaseで良さそう。
(個人的にGCPに集約したいだけ。)

参考リンク