firebase cloud functionsで処理速度を高めるための遅延ローディングをTypeScriptでやる際に、namespaceとかを使っているとやりにくかったのでメモ。
前提
TypeScriptでfirebase cloud functionsのコードを書いていて全体像はなんとなくこんな感じでした。
import { Foo } from "./foo";
export const doBar = Foo .bar;
export const doBaz = Foo .baz;
export namespace Foo {
export const bar = functions.firestore
.document("barDocuments/{barId}")
.onWrite(async (snapshot, context) => {
// do something...
});
export const baz= functions.https.onCall((data, context) => {
// do something...
});
}
動作が遅くなる問題
ただ、実はこれでは関数実行時の速度が遅くなります。
functionsは一つの関数呼び出しに対して仮想インスタンスが一つ作られ、一定時間アクセスがないと削除されます。
インスタンスの作成時(関数の実行時?)にindex.js
が読み込まれるわけですが、上のようにべた書きにすると実行しない関数のimportまでしてしまい、処理が遅くなります。
。。。といったことと解決策が https://tech.ginco.io/post/ginco-engineer-meetup-2018-cloud-functions/ に書いてあったので試してみたのですが、最初詰まりました。
サイトには process.env.FUNCTION_NAME
に実行予定の関数名が入っていることを利用して遅延読み込みするべしと書いてあります。
if (!process.env.FUNCTION_NAME || process.env.FUNCTION_NAME === 'Func1') {
const Foo= require('./foo');
exports.bar = Foo.bar;
}
ただ、これをTypeScriptでやろうとしたときに問題に遭遇しました。
TypeScriptで速度改善するときの問題と解決策
deploy時に関数が認識されない
configとかいじればいけるのか(?)もしれませんが、index.js
では最終的に
exports.baz = functions.https.onCall((data, context) => {
// do something...
});
と評価されないとfunctionだと認識してくれないようで、サイトのマルパクではdeployできませんでした。
これは、いったん関数はexportしたうえで、中で process.env.FUNCTION_NAME
を評価して解決します。
export const doBar= functions.https.onCall((data, context) => {
if (
!process.env.FUNCTION_NAME ||
process.env.FUNCTION_NAME === "doBar"
) {
// ...
}
return null;
});
namespace使ってるときに遅延読み込み & トランスパイル後の動作保証どうやるの問題
遅延読み込みは
import("hoge").then(loaded => /* do something... */ );
でいけますが、namespace?
結局、いろいろやっていたら
import("@/foo").then(({ Foo }) =>
Foo.bar(data, context)
);
でいけました。(勉強不足)
完成形
export const doBar= functions.firestore
.document("barDocuments/{barId}")
.onWrite(async (snapshot, context) => {
if (
!process.env.FUNCTION_NAME ||
process.env.FUNCTION_NAME === "doBar"
) {
return import("@/foo").then(({ Foo }) =>
Foo.bar(data, context)
);
}
return null;
});
export const doBaz= functions.https.onCall((data, context) => {
if (
!process.env.FUNCTION_NAME ||
process.env.FUNCTION_NAME === "doBaz"
) {
return import("@/foo").then(({ Foo }) =>
Foo.baz(data, context)
);
}
return null;
});
その他
- もちろん、これ以外にリージョンを東京にしたら早くなるとかあります。(ジェニさえ払えば速くなんでぇ)
- そもそもインスタンスのスペックを256MBのままにしてるのが無理ゲーという話もあります(ジェニさえ...(略))
ちゃんと勉強します。